-- UINewWorkshop
-- Create by cheny3
-- 新炼金工坊界面

require "game/ui/form/workshop/UIWorkshopDesc"
require "game/ui/form/workshop/UIWorkshopStore"
require "game/ui/form/workshop/UIWorkshopStrengthen"
require "game/ui/form/workshop/UIWorkshopConfig"
require "game/ui/form/workshop/UIGuideBuyEquip"
require "game/ui/form/workshop/UIMonthlyCard"
require "game/ui/form/guide/UIGuideMask"
require "game/ui/form/reagent/UIReagent"
require "game/ui/form/workshop/UIScoutInfo"
require "game/ui/base/AlignM"
require "game/ui/form/artifact/UIArtifactSelect"
require "game/ui/form/artifact/UIArtifactCompound"
require "game/ui/form/artifact/UIArtifactUpgrade"


--UINewWorkshop继承自Layer
UINewWorkshop = class("UINewWorkshop", function()
    return cc.Layer:create();
end);

function UINewWorkshop.create()
    return UINewWorkshop.new();
end

-- local resize;

-- 初始化常量
local WORKSHOP_TYPE   = 1;     -- 炼金工坊的场景类型
local DISAPPEAR_DELAY = 10;    -- 发言框持续时间

-- 药剂师冈布奥
PHAR_SLIME_ID = 28;
-- 炼金师冈布奥
ALCH_SLIME_ID = 10;

-- 工坊总数
local totalNum = 9;

-- 显示出来的工坊总数
local showtotalNum = totalNum;

-- 斥候冈布奥
local shadowList = {};
local slimeList = {};
local dustList = {};
local shadowOffset = {-4, 5, 8};   -- 阴影偏移
local slimeRunDistance = AlignM.frameSize.width / 2;
local workerShadowOffset = {{10, -1}, {5, -1}, {5, -1}};  -- 工匠阴影偏移

-- 构造函数
function UINewWorkshop:ctor()
    self:setName("UINewWorkshop");

    -- 初始化
    local node = cc.CSLoader:createNode("layout/workshop/NewWorkshop.csb");
    self:addChild(node);
    self.node = node;

    -- 斥候相关
    self.isPlayScoutEffect = false;
    self.isPlayScoutBtn = false;
    self.needPlayBagOpen = false;
    shadowList = {};
    slimeList = {};
    dustList = {};

    local textNode = UIMgr:getCurrentScene().topMenu:getMoneyTextNode();

    self:resize(self);

    local bt = findChildByName(node,"BT");
    local ct = findChildByName(node,"CT");

    self.storeLabel   = findChildByName(node,"bg/store");
    self.storePanel   = findChildByName(node,"bg/store_panel");
    self.storeIcon    = findChildByName(node,"bg/store_icon");
    self.furnaceLabel = findChildByName(node,"bg/furnace");
    self.furnacePanel = findChildByName(node,"bg/furnace_panel");
    self.artifactIcon = findChildByName(node,"bg/artifact");
    self.artifactRoom = findChildByName(node,"bg/artifact_room_panel");
    self.reagentIcon  = findChildByName(node,"bg/reagent");

    -- 收集当前的发言节点
    self.wordNodeList = {};
    local goOn = true;
    local i = 1;
    while goOn do
        local ch = findChildByName(node, "bg/words_node_" .. i);
        if not ch then
            break;
        else
            table.insert(self.wordNodeList, ch);
            i = i + 1;
        end
    end

    -- 炼金剩余时间
    local timeLabel = findChildByName(self.node, "bottom/left_time");
    TextStyleM.setTextStyle(timeLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_LIGHT_GREEN, false);
    local outlineColor = TextStyleM.TEXT_OUTLINE_COLOR_DARK;
    timeLabel:enableOutline(cc.c4b(outlineColor[1], outlineColor[2], outlineColor[3], 255), 1);

    -- 设置标题样式, 序章标题只有在引导时出现
    if not AlchemyWorkshopM.isAllGuideFinished() then
        local titleLabel = findChildByName(self.node, "TOP/title_bg/text");
        titleLabel:setString(getLocStr("preface"));
        titleLabel:setPositionY(titleLabel:getPositionY() - 3.5);
        TextStyleM.setArtWordTitleStyle(titleLabel);

        -- 从右边飞入
        local title = findChildByName(self.node, "TOP/title_bg");
        title:setPositionX(-2);
        title:setScale(1);
        title:setVisible(false);

        local delay = cc.DelayTime:create(1.5);
        local callFunc = cc.CallFunc:create(function()
            title:setVisible(true);
        end);
        local scale1 = cc.ScaleTo:create(0.2, 1.4);
        local scale2 = cc.ScaleTo:create(0.1, 1.1);
        local scale3 = cc.ScaleTo:create(0.1, 1.25);
        local scale4 = cc.ScaleTo:create(0.1, 1.2);
        title:runAction(cc.Sequence:create(delay, callFunc, scale1, scale2, scale3, scale4));
    end


    -- 炼金炉冒气特效
    local furnaceAnim = findChildByName(node,"bg/furnace_anim");
    playEffect(furnaceAnim, 1167, 27, 100);

    -- 检查仓库是否显示
    self:checkShowStore();

    -- 检查熔炉是否显示
    self:checkShowFurnace();

    -- 检查神器工坊显示
    self:checkArtifactRoom();

    -- 检查试剂工坊显示
    self:checkReagentRoom();

    -- 炼金师冈布奥/药剂师冈布奥的显示
    self:redrawSlime();

    -- TopMenu显示工人数
    UIMgr:getCurrentScene().topMenu:showWorkerInfo();
    UIMgr:getCurrentScene().topMenu:showMoneyInfo();

    -- 消耗掉未提示消息
    AlchemyWorkshopM.fetchBonusText();

    -- 注册点击处理回调
    self:registerTouchCallBack();

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 检查随机发言
    self:checkRandomWords();

    -- 检查月卡
    self:checkSign();
end

-- 显示炼金师冈布奥/药剂师冈布奥
function UINewWorkshop:redrawSlime()
    local alchNode = findChildByName(self.node, "bg/alchemist");
    local pharNode = findChildByName(self.node, "bg/pharmacist");
    local alchSlime = PetM.getMyPet(ALCH_SLIME_ID);
    local pharSlime = PetM.getMyPet(PHAR_SLIME_ID);

    if alchSlime then
        self:initItem(alchNode, ALCH_SLIME_ID);
    else
        alchNode:setVisible(false);
    end

    if pharSlime then
        self:initItem(pharNode, PHAR_SLIME_ID);
    else
        pharNode:setVisible(false);
    end
end

-- 冈布奥图标初始化
function UINewWorkshop:initItem(child, classId)
    if classId == nil then
        child:setVisible(false);
        return;
    end

    -- 显示冈布奥模型
    local headImg = child:getChildByName("icon");
    local iconPath = getHeroIconPath(PetM.getDefaultIcon(classId));

    headImg:loadTexture(iconPath);

    -- 炼金师冈布奥的图标需要水平翻转
    if classId == 10 then
        headImg:setScaleX(-1);
    end

    local oldScaleX = headImg:getScaleX();
    local oldScaleY = headImg:getScaleY();

    -- 图片需要播放呼吸效果
    local scaleUp   = cc.ScaleTo:create(1, 1 * oldScaleX, 1 * oldScaleY);
    local scaleDown = cc.ScaleTo:create(1, 1 * oldScaleX, 0.95 * oldScaleY);

    headImg:runAction(cc.RepeatForever:create(cc.Sequence:create(scaleUp, scaleDown)));

    -- 如果升阶中，则隐藏图标
    if TrainingM.isUpgrading(classId) or
        AwakeM.isCarving(classId) then
        headImg:setVisible(false);
    end
end

-- 没有资源的时候不显示 仓库资源
function UINewWorkshop:checkShowStore()
    if self.noCheckAgain then
        return;
    end

    local hideFlag = true;
    local groups = {15, 17, 19, 20, 21};
    local items = {};
    for i = 1, #groups do
        items = table.append(items, ItemM.getItemsByGroup(ME.user, groups[i]));
    end

    local itemNum = #items;
    for i = 1, itemNum do
        local classId = items[i];
        if ItemM.getAmount(ME.user, classId) ~= 0 then
            hideFlag = false;
            break;
        end
    end

    if hideFlag == true then
        self.storeLabel:setVisible(false);
        self.storePanel:setVisible(false);
        self.storeIcon:setVisible(false);
    else
        TextStyleM.setTextStyle(self.storeLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, nil, nil, nil, nil, nil, true);
        self.storeLabel:setString(getLocStr("store"));
        self.storeLabel:setFontSize(35);
        convertTextToArtWord(self.storeLabel, "images/ui/text_mask/text_mask3.png", TextStyleM.TEXT_COLOR_DARK_BROWN);
        self.storeLabel:setVisible(true);
        self.storePanel:setVisible(true);
        self.storeIcon:setVisible(true);

        -- 一旦显示了，就不要再次检查是否需要显示
        self.noCheckAgain = true;
    end
end

-- 打开熔炉
function UINewWorkshop:openFurnace()
    if self.isPlayScoutEffect then
        -- 正在播放动画,不响应
        return;
    end
    local uiForm = UIWorkshopStrengthen.create();
    UIMgr:getCurrentScene():addForm(uiForm);
    AudioM.playFx("ui_open1");
end

-- 注册点击处理回调
function UINewWorkshop:registerTouchCallBack()
    -- 熔炉点击处理
    self.furnacePanel:setTouchEnabled(true);
    self.furnacePanel:addTouchEventListener(function(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            self:openFurnace();
        elseif eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end);

    -- 熔炉泡泡点击处理
    local furnaceBubble = findChildByName(self.node, "bg/bubble");
    furnaceBubble:setLocalZOrder(1000);
    local bubbleBg = findChildByName(self.node, "bg/bubble/bg");
    bubbleBg:addTouchEventListener(function(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            self:openFurnace();
        elseif eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end);

    -- 仓库点击处理
    self.storePanel:setTouchEnabled(true);
    self.storePanel:addTouchEventListener(function(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            --AudioM.playFx("button_click");
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end
            -- 点击仓库资源
            local uiStore = UIWorkshopStore.create();
            UIMgr.getCurrentScene():addForm(uiStore);
        elseif  eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end);

    -- 神器工坊点击处理
    local function onArtifactRoomClick(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end
            -- 打开神器工坊
            local uiForm = UIArtifactSelect.create();
            UIMgr.getCurrentScene():addForm(uiForm);
            AudioM.playFx("workshop_open_ui");
        elseif  eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end

    self.artifactRoom:setTouchEnabled(true);
    self.artifactRoom:addTouchEventListener(onArtifactRoomClick);

    -- 神器工坊泡泡点击处理
    local artifactBubble = findChildByName(self.node, "bg/artifact_bubble");
    artifactBubble:setLocalZOrder(1000);
    local artifactBubbleBg = findChildByName(self.node, "bg/artifact_bubble/bg");
    artifactBubbleBg:addTouchEventListener(onArtifactRoomClick);

    local reagentBubble = findChildByName(self.node, "bg/reagent_bubble");
    local reagentBubbleBg = findChildByName(self.node, "bg/reagent_bubble/bg");
    local reagentPanel = findChildByName(self.node, "bg/reagent_panel");
    -- 试剂工坊点击处理
    local function onReagentRoomClick(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            if not self.reagentIcon:isVisible() then
                return;
            end
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end
            -- 打开神器工坊
            local uiForm = UIReagent.create();
            UIMgr.getCurrentScene():addForm(uiForm);
            AudioM.playFx("workshop_open_ui");
            ME.user.dbase:set("have_new_reagent", 0);
            reagentBubble:setVisible(false);

            Operation.cmd_view_new_reagent();
        elseif  eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end

    reagentPanel:addTouchEventListener(onReagentRoomClick);
    self.reagentPanel = reagentPanel;

    -- 试剂工厂泡泡点击处理
    reagentBubble:setLocalZOrder(1000);
    reagentBubbleBg:addTouchEventListener(onReagentRoomClick);

    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.node,"BT/btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_return");
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end
            -- 关闭当前界面
            UIMgr.getCurrentScene():removeFormByName("UINewWorkshop");
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);
    TextStyleM.setTextStyle(btnBack,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    -- 注册配置按钮点击事件
    local btnSet = findChildByName(self.node,"BT/setting");
    local function onSettingClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end
            local uiForm = UIWorkshopConfig.create()
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    AddTouchEventListener(btnSet, onSettingClick);
    TextStyleM.setTextStyle(btnSet,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnSet:setTitleText(getLocStr("setting"));

    -- 斥候探索按钮点击事件
    local btnScout = findChildByName(self.node, "BT/scout");
    local btnText = findChildByName(btnScout, "text");
    local btnText2 = findChildByName(btnScout, "text2");
    local kerning = 0;
    if getLang() ~= "zh" then
        btnText = findChildByName(btnScout, "text_en");
        btnText2 = findChildByName(btnScout, "text2_en");
        kerning = -4;
    end
    local function onScoutClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            if self.isPlayScoutEffect then
                -- 正在播放动画,不响应
                return;
            end

            if UIMgr.getCurrentScene():getFormByName("UIScoutInfo") ~= nil then
                -- 界面已经打开
                return;
            end

            if ScoutM.canStartExplore() then
                -- 发起请求
                -- ScoutM.startExplore();
                -- 播放斥候跑出去的特效(会自行打开界面)
                self:playScoutOutEffect(ScoutM.getScoutCount());
            elseif ScoutM.isExploring() then
                -- 正在探索，直接打开界面
                local uiScout = UIScoutInfo.create(false, false);
                UIMgr.getCurrentScene():addForm(uiScout);
            end
        end
    end
    AddTouchEventListener(btnScout, onScoutClick);
    TextStyleM.setTextStyle(btnScout,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    TextStyleM.setTextStyle(btnText,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, kerning);
    TextStyleM.setTextStyle(btnText2,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    self:redrawScoutBtn();

    -- 背景图点击回调
    local bg = findChildByName(self.node, "bg");
    bg:addTouchEventListener(function(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            local beganPos = sender:getTouchBeganPosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(beganPos);
        elseif eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos);
        end
    end);

    -- 按钮回调
    local foldImg = findChildByName(self.node,"bottom/bg/fold");
    local scrollviewBg = findChildByName(self.node,"bottom/bg");
    local function onFoldClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            local foldConfig = ME.user.dbase:queryTemp("foldConfig", 0);
            foldConfig = (foldConfig + 1) % 2;
            ME.user.dbase:setTemp("foldConfig", foldConfig);
            self:updateFoldConfig();
        end
    end
    foldImg:addTouchEventListener(onFoldClick);
    scrollviewBg:addTouchEventListener(onFoldClick);

    -- 注册牌子点击事件
    local signImg = findChildByName(self.node, "bg/sign");
    local function onSignClick(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            signImg:runAction(cc.ScaleTo:create(0.1, 0.97));
        elseif eventType == ccui.TouchEventType.canceled then
            signImg:runAction(cc.ScaleTo:create(0.1, 1));
        elseif eventType == ccui.TouchEventType.ended then
            signImg:runAction(cc.ScaleTo:create(0.1, 1));
            if SuperiorM.isOverdue() then
                signImg:setVisible(false);
                alert(getLocStr("superior_is_overdue"));
            else
                UIMgr.getCurrentScene():removeFormByName("UIMonthlyCard");
                local uiForm= UIMonthlyCard.create();
                UIMgr.getCurrentScene():addForm(uiForm);
            end
        end
    end
    signImg:addTouchEventListener(onSignClick);
end

-- 注册事件处理回调函数
function UINewWorkshop:registerEventCallback()
    -- 注册事件
    EventMgr.register("UINewWorkshop", event.ITEM_COUNT_UPDATED, function()
        self:checkShowStore();
    end);

    -- 注册工坊信息更新回调
    EventMgr.register("UINewWorkshop", event.WORKSHOP_INFO_UPDATED, function()
        self:initScrollView();

        local isConfigFormOpen = UIMgr.getCurrentScene():isOpen("UIWorkshopConfig");
        if AlchemyWorkshopM.isGuideFinished(5) and not isConfigFormOpen then
            UIMgr:getCurrentScene().topMenu:updateWorkerInfo();
        end

        -- 工人出现
        local totalNum = math.min(AlchemyWorkshopM.getTotalWorkerNum(), 10);
        local workingNum = self:getWorkingNum();
        local leftNum = totalNum - workingNum;

        for i = 1, leftNum do
            self:workerRunIn(true);
        end
        if leftNum > 0 then
            local level = AlchemyWorkshopM.getStrengthenLevel(2);
            local function appearDialog()
               self:showWordsDialog(level);
            end
            local delay = 4.5;
            performWithDelay(self, appearDialog, delay);
        end

        -- 提示消息
        local bt = findChildByName(self.node, "BT");
        local bg = findChildByName(self.node, "bottom/bg");
        bg.gainItemList = AlchemyWorkshopM.genBriefText();
        if bt:isVisible() then
            print("show brief text");

            local function createTextFunc(color, str)
                local text = ccui.Text:create();
                text:setFontName(getLocFontName());
                text:setFontSize(36);
                text:setString(str);
                text:setTextColor(color);
                text:setAnchorPoint(cc.p(0, 0.5));
                local outlineColor = TextStyleM.TEXT_COLOR_DARK_BROWN;
                text:enableOutline(cc.c4b(outlineColor[1], outlineColor[2], outlineColor[3], 255), 2);
                text:enableShadow(TextStyleM.TEXT_OUTLINE_COLOR_DARK, cc.size(3, -3));
                text:getVirtualRenderer():setAdditionalKerning(getLocKerning() -4);
                text:setScale(0.8);
                return text;
            end

            showItemName(bg, TextStyleM.TEXT_COLOR_BRIGHT_YELLOW, 30, bg:getContentSize().height + 6, createTextFunc);
        end

        -- 检查引导进度
        self:checkGuide();
    end);

    -- 注册时间更新回调
    EventMgr.register("UINewWorkshop", event.WORKSHOP_LEFT_TIME, function(params)
        self:updateLeftTimeLabel(params["min"], params["sec"]);
    end);

    -- 金币变动的回调处理
    ME.user.dbase:registerCb("UINewWorkshop", { "money", }, function()
        self:checkShowFurnace();

        if self.checkBuyEquipBubble then
            self:showBuyEquipBubble();
        end
    end);

    EventMgr.register("UINewWorkshop", event.WS_STRENGTHEN_INFO, function()
        self:checkShowFurnace();

        -- 检查引导进度
        self:checkGuide();

        -- 检查神器工坊显示
        self:checkArtifactRoom();

        -- 检查试剂工坊显示
        self:checkReagentRoom();

        -- 设置灵魂链接I提醒标记
        if AlchemyWorkshopM.getStrengthenLevel(20) > 0
            and FeatureItemM.isFeatureNeedReminder("soulstone1") then
            FeatureItemM.markAsReminded("soulstone1");
        end

        -- 检查是否需要还原炼金泡泡的蒙版效果
        self:restoreWorkshopBubble();
    end);

    -- 更新斥候按钮
    EventMgr.register("UINewWorkshop", event.USER_INFO_UPDATED, function()
        self:redrawScoutBtn();
    end);

    -- 更新斥候信息
    EventMgr.register("UINewWorkshop", event.SCOUT_INFO_UPDATE, function()
        self:redrawScoutBtn();
    end);

    -- 炼金强化泡泡已提醒
    EventMgr.register("UINewWorkshop", event.WORKSHOP_ITEM_REMINDED, function()
        self:checkWorkshopBubble();
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UINewWorkshop", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UINewWorkshop" then
            if AlchemyWorkshopM.isAllGuideFinished() and para["lose"] ~= "UIWorkshopConfig" then
                UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_WORKER);
            end
            if para["lose"] == "UISystemSetting" then
                self:showBottomMenu();
            end
            if AlchemyWorkshopM.isAllGuideFinished() then
                FormEffectM.btPopUpFromBottom(self);
            end
        end
    end);

    EventMgr.register("UINewWorkshop", event.SUPERIOR_UPGRADE, function()
        self:checkSign();
    end);

    EventMgr.register("UINewWorkshop", event.TAKE_SUPERIOR_BONUS, function()
        self:checkSign();
    end);

    self:registerScriptHandler(function(ev)
        if ev == "exit" then
            if UIMgr.getCurrentScene().mainMap then
                UIMgr.getCurrentScene().mainMap:show();
            end

            -- 刷新金币
            if self.pickUpGolds then
                Operation.cmd_pickup_workshop_gold(self.pickUpGolds);
                self.pickUpGolds = 0;
            end

            -- 清除斥候冈布奥
            self:removeScout();

            -- 清除回调
            EventMgr.removeAll("UINewWorkshop");

            ME.user.dbase:removeCb("UINewWorkshop", { "money", });

            UIMgr.tryClearUnusedTextures();
        elseif ev == "enter" then
            UIMgr.getCurrentScene().mainMap:hide();

            -- 播放界面音效
            AudioM.playFx("workshop_open_ui");

            -- 初始化配置列表
            self:initScrollView();

            -- 初始化折叠配置和倒计时
            self:updateFoldConfig();
            self:updateLeftTimeLabel();

            -- 设置炼金剩余时间
            local uiForm = UIMgr.getCurrentScene():getFormByName("UIMainMap");
            if uiForm then
                self.workShopLeftTime = uiForm:getWorkShopTime();
                self:updateLeftTimeLabel(self.workShopLeftTime["min"], self.workShopLeftTime["sec"]-1);
            end

            -- 初始化引导相关
            self:initGuide();

            -- 检查引导进度
            self:checkGuide();

            -- 依次检查是否有提醒
            self:checkReminder("");
        end
    end);
end

-- 依次检查是否有提醒
function UINewWorkshop:checkReminder()
    local function callback(desc)
        local function okFunc()
            -- 继续检查是否还有其他提醒
            self:checkReminder();
        end

        confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), desc, okFunc);
    end

    local checkList = { "reagent", "horse", "waterbox", "tent", "statue", "soulstone1", "altar", "treasure", "throne", "soulstone2" };
    -- 检查进度提醒
    if not self.checkProgress then
        self.checkProgress = 1;
    end

    for i = self.checkProgress, #checkList do
        local ret = FeatureItemM.checkReminder(checkList[i], callback);
        if ret == true then
            -- 每次检查一个提醒，确认后再继续
            self.checkProgress = i + 1;
            return;
        end
    end

    -- 检查试剂的提醒
    local newReagent = ME.user.dbase:query("have_new_reagent");
    if AlchemyWorkshopM.getStrengthenLevel(18) > 0 and newReagent > 0 then
        local hasCue = ME.user.dbase:query("has_cue", 0);
        if newReagent ~= hasCue then
            ME.user.dbase:set("has_cue", newReagent);
            local desc = string.format(getLocStr("new_reagent"), ItemM.query(ReagentM.queryGoodsInfo(newReagent)[2], "name"));
            confirm2(CONFIRM_TYPE_OK, getLocStr("slime_note"), desc);
        end
    end
end

-- 斥候跑出去动画
function UINewWorkshop:playScoutOutEffect(showNum)
    self.isPlayScoutEffect = true;

    -- 加蒙版，不让点击
    local mask = findChildByName(self.node, "mask");
    mask:setVisible(true);
    mask:setOpacity(0);

    -- 按钮置灰
    local btnScout = findChildByName(self.node, "BT/scout");
    btnScout:setTouchEnabled(false);
    btnScout:setBright(false);

    -- 清除泡泡
    local hintNode =  findChildByName(btnScout, "hint");
    checkBlueBubbleStatus(hintNode, false);

    -- 清除斥候跳跃动画
    self:removeScout();
    AudioM.playFx("explore");
    local posParent = findChildByName(self.node, "bottom/pos_parent");
    posParent:stopAllActions();

    if showNum > 3 then
        showNum = 3;
    end

    -- 先创建阴影,保证所有阴影在冈布奥后面
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local shadow = ccui.ImageView:create();
        shadowList[i] = shadow;
        shadow:setScale(0.8);
        posParent:addChild(shadow);
        shadow:setPosition(cc.p(pos:getPositionX(), pos:getPositionY() + 2));
        shadow:loadTexture("images/ui/workshop/shadow2.png", 1);
        shadow:setVisible(true);
    end

    -- 创建灰尘节点
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local dustNode = cc.Node:create();
        if dustList[i] ~= nil then
            dustList[i]:removeAllChildren();
        end
        dustList[i] = dustNode;
        posParent:addChild(dustNode);
        dustNode:setPosition(cc.p(pos:getPositionX() - 25, pos:getPositionY() + 15));
    end

    -- 创建节点
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local slime = cc.Node:create();
        local slimeIcon = ccui.ImageView:create();
        slimeIcon:setAnchorPoint(cc.p(0.5, 0));
        slimeIcon:loadTexture(getScoutIconPath(showNum - i + 1));
        posParent:addChild(slime);
        slimeIcon:setFlippedX(true);
        slime:addChild(slimeIcon);
        slime:setPosition(cc.p(pos:getPositionX(), pos:getPositionY()));
        slimeList[showNum - i + 1] = slime;
    end

    -- 跑出屏幕动画
    local function moveOut()
        -- 灰尘节点
        local countList = {0, 0, 0};

        local function showDust(dustFlag)
            local dustNode = dustList[dustFlag];
            dustNode:removeAllChildren();
            playEffect(dustNode, 1503, slimeRunDistance / 10 * countList[dustFlag], -15, nil);
        end

        for i = 1, showNum do
            local function showDustPlay()
                showDust(i);
                if countList[i] < 10 then
                    performWithDelay(self.node, showDustPlay, 0.1);
                else
                    dustList[i]:removeAllChildren();
                end
                countList[i] = countList[i] + 1;
            end
            showDustPlay();
        end

        for i = 1, showNum do
            local slimeNode = slimeList[i];
            local shadowNode = shadowList[i];
            local jumps = math.ceil(10);
            --local height = math.random(3, 5);
            local height = 0;

            local jumpBy = cc.JumpTo:create(0.1 * jumps, cc.p(slimeNode:getPositionX() + slimeRunDistance,
                slimeNode:getPositionY()), height, jumps);
            local jumpBy2 = cc.JumpTo:create(0.1 * jumps, cc.p(shadowNode:getPositionX() + slimeRunDistance,
                shadowNode:getPositionY()), 0, jumps)
            slimeNode:runAction(jumpBy);
            shadowNode:runAction(jumpBy2);
        end

        -- 移除所有节点
        local function removeNode()
            self:removeScout();

            -- 打开斥候探索界面
            local uiScout = UIScoutInfo.create(true, true);
            UIMgr.getCurrentScene():addForm(uiScout);

            -- 按钮恢复
            local btnScout = findChildByName(self.node, "BT/scout");
            btnScout:setTouchEnabled(true);
            btnScout:setBright(true);

            for i = 1, showNum do
               dustList[i]:removeAllChildren();
            end

            local function callBack()
                self.isPlayScoutEffect = false;
                -- 去掉蒙版
                local mask = findChildByName(self.node, "mask");
                mask:setVisible(false);
            end

            performWithDelay(self, callBack, 0.5);
        end
        performWithDelay(posParent, removeNode, 1);
    end

    -- 跑出去动画
    moveOut();
end

-- 斥候跑进来动画
function UINewWorkshop:playScoutInEffect(showNum)
    self.isPlayScoutEffect = true;

    -- 加蒙版，不让点击
    local mask = findChildByName(self.node, "mask");
    mask:setVisible(true);
    mask:setOpacity(0);

    -- 按钮置灰
    local btnScout = findChildByName(self.node, "BT/scout");
    btnScout:setTouchEnabled(false);
    btnScout:setBright(false);

    -- 清除泡泡
    local hintNode =  findChildByName(btnScout, "hint");
    checkBlueBubbleStatus(hintNode, false);

    -- 清除斥候所有动画
    self:removeScout();
    AudioM.playFx("explore");
    local posParent = findChildByName(self.node, "bottom/pos_parent");
    posParent:stopAllActions();

    if showNum > 3 then
        showNum = 3;
    end

    -- 先创建阴影,保证所有阴影在冈布奥后面
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local shadow = ccui.ImageView:create();
        shadowList[i] = shadow;
        shadow:setScale(0.8);
        posParent:addChild(shadow);
        shadow:setPosition(cc.p(pos:getPositionX() + slimeRunDistance + shadowOffset[showNum - i + 1],
            pos:getPositionY() + 2));
        shadow:loadTexture("images/ui/workshop/shadow2.png", 1);
        shadow:setVisible(true);
    end

    -- 创建灰尘节点
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local dustNode = cc.Node:create();
        if dustList[i] ~= nil then
            dustList[i]:removeAllChildren();
        end
        dustList[i] = dustNode;
        dustNode:setScaleX(-1);
        posParent:addChild(dustNode);
        dustNode:setPosition(cc.p(pos:getPositionX() + slimeRunDistance + 40, pos:getPositionY() + 15));
    end

    -- 创建节点
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local slime = cc.Node:create();
        local slimeIcon = ccui.ImageView:create();
        slimeIcon:setAnchorPoint(cc.p(0.5, 0));
        slimeIcon:loadTexture(getScoutIconPath(showNum - i + 1));
        posParent:addChild(slime);
        slime:addChild(slimeIcon);
        slime:setPosition(cc.p(pos:getPositionX() + slimeRunDistance, pos:getPositionY()));
        slimeList[i] = slime;
    end

    -- 跑进屏幕动画
    local function moveIn()
        -- 灰尘节点
        local countList = {0, 0, 0};

        local function showDust(dustFlag)
            local dustNode = dustList[dustFlag];
            dustNode:removeAllChildren();
            playEffect(dustNode, 1503, slimeRunDistance * (countList[dustFlag]) / 10, -15, nil);
        end

        for i = 1, showNum do
            local function showDustPlay()
                showDust(i);
                if countList[i] < 10 then
                    performWithDelay(self.node, showDustPlay, 0.1);
                else
                    dustList[i]:removeAllChildren();
                end
                countList[i] = countList[i] + 1;
            end
            showDustPlay();
        end

        for i = 1, showNum do
            local slimeNode = slimeList[i];
            local shadowNode = shadowList[i];
            local jumps = math.ceil(10);
            --local height = math.random(3, 5);
            local height = 0;

            local jumpBy = cc.JumpTo:create(0.1 * jumps, cc.p(slimeNode:getPositionX() - slimeRunDistance,
                slimeNode:getPositionY()), height, jumps);
            local jumpBy2 = cc.JumpTo:create(0.1 * jumps, cc.p(shadowNode:getPositionX() - slimeRunDistance,
                shadowNode:getPositionY()), 0, jumps)
            slimeNode:runAction(jumpBy);
            shadowNode:runAction(jumpBy2);
        end

        -- 移除所有节点
        local function removeNode()
            -- 灰尘节点
            for i = 1, showNum do
                dustList[i]:removeAllChildren();
            end

            local function scoutBagEffect()
                self:removeScout();

                -- 先创建阴影,保证所有阴影在冈布奥后面
                for i = 1, showNum do
                    local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
                    local shadow = ccui.ImageView:create();
                    shadowList[i] = shadow;
                    shadow:setScale(0.8);
                    posParent:addChild(shadow);
                    shadow:setPosition(cc.p(pos:getPositionX() + shadowOffset[i], pos:getPositionY()));
                    shadow:loadTexture("images/ui/workshop/shadow2.png", 1);
                    shadow:setVisible(true);
                end

                for i = 1, showNum do
                    local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
                    local slime = cc.Node:create();
                    slimeList[i] = slime;
                    slime:setPosition(pos:getPositionX(), pos:getPositionY());
                    posParent:addChild(slime);
                    -- 斥候背包动画
                    self:playScoutEffect(slime, 1500 + showNum - i);
                end
            end

            local function callBack()
                self:removeScout();
                self.isPlayScoutEffect = false;

                -- 去掉蒙版
                local mask = findChildByName(self.node, "mask");
                mask:setVisible(false);

                -- 按钮恢复
                local btnScout = findChildByName(self.node, "BT/scout");
                btnScout:setTouchEnabled(true);
                btnScout:setBright(true);

                -- 显示泡泡
                local hintNode =  findChildByName(btnScout, "hint");
                checkBlueBubbleStatus(hintNode, true);

                -- 斥候动画
                self:scoutJump(ScoutM.getScoutCount());
            end

            if self.needPlayBagOpen then
                scoutBagEffect();
            else
                performWithDelay(posParent, callBack, 0.2);
            end
        end
        performWithDelay(posParent, removeNode, 1);
    end

    -- 跑进动画
    moveIn();
end

-- 播放特效
function UINewWorkshop:playScoutEffect(parentNode, effectId)
    local effectAniam = createEffectAnim(effectId);
    effectAniam:setPositionY(effectAniam:getPositionY());
    parentNode:addChild(effectAniam);
    -- 71祯开始/116祯结束
    effectAniam:play(71, 116);
end

-- 设置需要播放斥候背包打开动作
function UINewWorkshop:setNeedPlayBagOpen(need)
    self.needPlayBagOpen = need;
end

local scoutBtnCount = 1;

-- 斥候按钮探索中...
function UINewWorkshop:redrawScoutBtnPlay()
    local scoutBtn = findChildByName(self.node, "BT/scout");
    local hintNode =  findChildByName(scoutBtn, "hint");
    local btnText = findChildByName(scoutBtn, "text");
    local btnText2 = findChildByName(scoutBtn, "text2");
    local kerning = -6;
    if getLang() ~= "zh" then
        btnText = findChildByName(scoutBtn, "text_en");
        btnText2 = findChildByName(scoutBtn, "text2_en");
        kerning = -3;
    end
    local hasPlay = false;

    if self.isPlayScoutBtn == true then
        return;
    end

    scoutBtn:setTitleText("");
    local text = getLocStr("searching");
    btnText:getVirtualRenderer():setAdditionalKerning(getLocKerning() -4);
    TextStyleM.setShadowStyle(btnText, cc.size(0, -2.5));
    TextStyleM.setOutlineStyle(btnText, 1.6, TEXT_OUTLINE_COLOR, true);
    btnText:setString(text);
    btnText:setVisible(true);
    btnText2:setVisible(true);

    local function tick()
        self.isPlayScoutBtn = true;
        if not ScoutM.isExploring() then
            self:redrawScoutBtn();
            self.isPlayScoutBtn = false;
            return;
        end

        if ScoutM.getLeftTime() <= 0 then
            if not hasPlay then
                hasPlay = true;
                checkBlueBubbleStatus(hintNode, true);
            end
        else
            checkBlueBubbleStatus(hintNode, false);
        end

        -- 正在探索
        local text2 = "";
        for i = 1, scoutBtnCount do
            text2 = text2 .. ".";
        end
        scoutBtnCount = math.ceil(scoutBtnCount % 3 + 1)
        btnText2:setString(text2);
        btnText2:getVirtualRenderer():setAdditionalKerning(getLocKerning() + kerning);
        TextStyleM.setShadowStyle(btnText2, cc.size(0, -2.5));
        TextStyleM.setOutlineStyle(btnText2, 1.6, TEXT_OUTLINE_COLOR, true);
        performWithDelay(self.node, tick, 0.5);
    end

    tick();

end

-- 更新斥候按钮
function UINewWorkshop:redrawScoutBtn()
    local btnScout = findChildByName(self.node, "BT/scout");
    local btnText = findChildByName(btnScout, "text");
    local btnText2 = findChildByName(btnScout, "text2");
    if getLang() ~= "zh" then
        btnText = findChildByName(btnScout, "text_en");
        btnText2 = findChildByName(btnScout, "text2_en");
    end
    btnScout:setVisible(true);

    local hintNode = findChildByName(btnScout, "hint");
    local hintIcon =  findChildByName(hintNode, "icon");

    if ScoutM.canStartExplore() then
        -- 可以探索
        btnScout:setTitleText(getLocStr("search"));
        TextStyleM.setTextStyle(btnScout,TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
        btnText:setString("");
        btnText2:setString("");

        if not self.isPlayScoutEffect then
            -- 斥候动画
            self:scoutJump(ScoutM.getScoutCount());

            -- 显示泡泡
            checkBlueBubbleStatus(hintNode, true);
        end
    elseif ScoutM.isExploring() then
        -- 正在探索
        -- 按钮表现
        self:redrawScoutBtnPlay();
        if not self.isPlayScoutEffect then
            -- 去掉斥候动画
            self:removeScout();
        end
    else
        -- 没有斥候
        btnScout:setVisible(false);
        -- 去掉斥候动画
        self:removeScout();
    end

end

-- 初始化折叠配置
function UINewWorkshop:updateFoldConfig()
    -- 折叠按钮回调
    local foldConfig = ME.user.dbase:queryTemp("foldConfig", 0);
    local bg = findChildByName(self.node,"bottom/bg");
    local scrollview = findChildByName(self.node,"bottom/scrollview");
    local leftTimeLabel = findChildByName(self.node,"bottom/left_time");
    local foldImg = findChildByName(self.node,"bottom/bg/fold");

    -- 记录下scrollview的初始宽高
    if self.scrollInitCont == nil then
        self.scrollInitCont = scrollview:getContentSize();
    end

    local expandWidth = tonumber(self.expandWidth);

    if foldConfig == 1 then
        -- 折叠
        bg:setContentSize(192, 49);
        scrollview:setVisible(false);
        leftTimeLabel:setPositionY(148);
        foldImg:loadTexture("images/ui/workshop/unfold.png");
        foldImg:setPositionX(150);
        foldImg:setPositionY(23.5);
    else
        bg:setContentSize(300 + expandWidth, 220);

        scrollview:setContentSize(self.scrollInitCont.width + expandWidth, self.scrollInitCont.height);
        scrollview:setVisible(true)

        leftTimeLabel:setPositionY(315);
        leftTimeLabel:setPositionX(-270);
        foldImg:loadTexture("images/ui/workshop/fold.png");
        foldImg:setPositionX(260 + expandWidth);
        foldImg:setPositionY(189);
    end
end

-- 更新倒计时
function UINewWorkshop:updateLeftTimeLabel(min, sec)
    min = min or 0;
    sec = sec or 0;
    min = iif(min < 0, 0, min);
    sec = iif(sec < 0, 0, sec);

    local timeLabel = findChildByName(self.node, "bottom/left_time");
    if timeLabel ~= nil then
        timeLabel:setString(string.format("%02d:%02d", min, sec));
        if AlchemyWorkshopM.getTotalWorkerNum() == AlchemyWorkshopM.getIdleWorkerNum() then
            -- 没有工作学徒，则隐藏
            timeLabel:setVisible(false);
        else
            timeLabel:setVisible(true);
        end
    end

    -- 斥候按钮

end

-- 没有任何开启物品的时候不显示熔炉
function UINewWorkshop:checkShowFurnace()
    local furnaceLabel = findChildByName(self.node, "bg/furnace");
    local furnacePanel = findChildByName(self.node, "bg/furnace_panel");

    local list = table.values(AlchemyWorkshopM.getStrengthenList());
    if #list == 0 then
        furnaceLabel:setVisible(false);
        furnacePanel:setVisible(false);
    else
        if furnaceLabel:isVisible() then
            TextStyleM.setTextStyle(furnaceLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
            furnaceLabel:setString(getLocStr("furnace"));
            convertTextToArtWord(furnaceLabel, "images/ui/text_mask/text_mask3.png", TextStyleM.TEXT_COLOR_DARK_BROWN);
            furnaceLabel:setVisible(true);
        end

        furnacePanel:setVisible(true);
    end

    -- 检查炼金炉上的泡泡是否显示
    self:checkWorkshopBubble();
end

-- 检查炼金炉上的泡泡是否显示
function UINewWorkshop:checkWorkshopBubble()
    local bubble = findChildByName(self.node, "bg/bubble");
    if AlchemyWorkshopM.readyForStrengthen() then
        if AlchemyWorkshopM.getStrengthenLevel(1) == 0 then
            self:highlightWorkshopBubble();
            return;
        end

        bubble:setVisible(true);
        if not bubble.isPlaying then
            bubble:stopAllActions();
            bubble:setScale(1);
            playBubbleAnima(bubble, true, 0.88);
            bubble.isPlaying = true;
        end
    else
        bubble:setVisible(false);
        bubble.isPlaying = false;
    end
end

-- 检查神器工坊显示
function UINewWorkshop:checkArtifactRoom()
    local panel = findChildByName(self.node, "bg/artifact_room_panel");

    local level = AlchemyWorkshopM.getStrengthenLevel(16);
    if level > 0 then
        panel:setVisible(true);
        self.artifactIcon:setVisible(true);
    else
        panel:setVisible(false);
        self.artifactIcon:setVisible(false);
    end

    -- 如果神器可以合成或升阶的话，显示泡泡
    local bubble = findChildByName(self.node, "bg/artifact_bubble");
    if ArtifactM.canArtifactUpgradeOrCompound("scarpNeed") and panel:isVisible() then
        bubble:setVisible(true);
        playBubbleAnima(bubble, true, 0.58);
    else
        bubble:setVisible(false);
    end
end

-- 检查试剂工坊显示
function UINewWorkshop:checkReagentRoom()
    -- 有获得任意图纸，则显示试剂工坊
    if AlchemyWorkshopM.getStrengthenLevel(18) > 0  then
        self.reagentIcon:setVisible(true);
    else
        self.reagentIcon:setVisible(false);
    end

    local newReagent = ME.user.dbase:query("have_new_reagent");
    -- 显示泡泡
    local bubble = findChildByName(self.node, "bg/reagent_bubble");
    bubble:setVisible(false);
    if AlchemyWorkshopM.getStrengthenLevel(18) > 0 and newReagent > 0 then
        bubble:setVisible(true);
        playBubbleAnima(bubble, true, 0.7);
    else
        bubble:setVisible(false);
    end
end

-- 播放试剂工厂建造动画
function UINewWorkshop:playBuildReagentEffect()
    self.reagentIcon:setVisible(false);

    local bubble = findChildByName(self.node, "bg/reagent_bubble");
    local oldBubbleVisible = bubble:isVisible();
    bubble:setVisible(false);

    local _, effect = playEffect(self.reagentPanel, 1151, 90, 70);

    local function callback()
        bubble:setVisible(oldBubbleVisible);
        effect:setVisible(false);
        self.reagentIcon:setVisible(true);
        self.reagentPanel:removeAllChildren();
        self:checkReagentRoom();
    end

    performWithDelay(self, callback, 1);
end

-- 播放神器工坊建造动画
function UINewWorkshop:playBuildArtifactRoomEffect()
    self.artifactIcon:setVisible(false);

    local bubble = findChildByName(self.node, "bg/artifact_bubble");
    local oldBubbleVisible = bubble:isVisible();
    bubble:setVisible(false);

    local _, effect = playEffect(self.artifactRoom, 1151, 80, 60);

    local function callback()
        bubble:setVisible(oldBubbleVisible);
        effect:setVisible(false);
        self.artifactIcon:setVisible(true);
        self.artifactRoom:removeAllChildren();
        self:checkReagentRoom();
    end

    performWithDelay(self, callback, 1);
end

-- 配置列表
function UINewWorkshop:initScrollView()
    local scrollview = findChildByName(self.node,"bottom/scrollview");
    scrollview:removeAllChildren();

    --左边距
    local leftMargin = 18;

    --行间距
    local gap = 3;

    local widgetHeight = 28;
    local startHeight = (widgetHeight + gap) / 2;

    local workshop = AlchemyWorkshopM.getWorkshop();
    local show_amount = 0;

    -- 要显示的行数
    for i = 1, totalNum do
        if workshop[i] ~= 0 then
            show_amount = show_amount + 1;
        end
    end

    -- 计算总高度
    local totalHeight = math.max(show_amount * (widgetHeight + gap), scrollview:getContentSize().height);

    -- 根据要显示的数目调整容器内高
    scrollview:setInnerContainerSize(cc.size(scrollview:getInnerContainerSize().width, totalHeight));

    if totalHeight < scrollview:getInnerContainerSize().height then
        startHeight = scrollview:getInnerContainerSize().height - totalHeight - 15;
    end

    local item = findChildByName(self.node, "bottom/item");
    item:setVisible(false);

    self.workshopChildren = {};
    local count = 2;
    self.expandWidth = 0;

    for i = 1, totalNum do
        -- 判断是否要显示
        if workshop[i] ~= 0 then
            local child = item:clone();
            child:setAnchorPoint(cc.p(0, 0));
            child:setPositionX(leftMargin);
            child:setPositionY(startHeight + totalHeight - count * (widgetHeight + gap));
            child:setTag(i);
            count = count + 1;

            scrollview:addChild(child);
            self.workshopChildren[i] = child;

            -- 绘制工人信息
            self:updateWorkshop(i);
        end
    end

    -- 更新下背景
    self:updateWorkshopWidth();

    local scrollviewBg = findChildByName(self.node,"bottom/bg");

    if AlchemyWorkshopM.getTotalWorkerNum() == AlchemyWorkshopM.getIdleWorkerNum() then
        -- 没有工作学徒，则隐藏
        scrollview:setVisible(false);
        scrollviewBg:setVisible(false);
    else
        if ME.user.dbase:queryTemp("foldConfig", 0) == 0 then
            scrollview:setVisible(true);
        else
            scrollview:setVisible(false);
        end
        scrollviewBg:setVisible(true);
    end

    -- 如果有空闲的工人，则显示蓝色泡泡
    local hintNode = findChildByName(self.node, "BT/setting/hint");
    local idleNum = AlchemyWorkshopM.getIdleWorkerNum();
    checkBlueBubbleStatus(hintNode, idleNum);
end

-- 更新工坊工人信息
function UINewWorkshop:updateWorkshop(type)
    -- 起始道具ID
    local startItemId = 1001;
    local itemid = startItemId + type - 1;

    local child = self.workshopChildren[type];

    -- 名称
    local name = findChildByName(child, "name");
    local nameTxt = ItemM.query(itemid, "name");

    if itemid == 1001 then
        nameTxt = getLocStr("money");
    end

    local child = self.workshopChildren[type];
    child:setVisible(true);

    -- 设置工人名称
    local kerning = -3;
    if not isFullWidthLang() then
        kerning = -3;
    end
    local nameLabel = findChildByName(child, "name");
    TextStyleM.setTextStyle(nameLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BEIGE, true, kerning);
    nameLabel:setString(nameTxt);

    -- 设置工人数量
    local workshop = AlchemyWorkshopM.getWorkshop();
    local countLabel = findChildByName(child, "count");
    TextStyleM.setTextStyle(countLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BEIGE, true, kerning);
    countLabel:setString(workshop[type]);

    -- 动态适应宽度
    local nameLabelWidth = nameLabel:getContentSize().width;
    local countLabelWidth = countLabel:getContentSize().width;

    local namePosX = nameLabel:getPositionX();

    local countPosX = countLabel:getPositionX();

    local posDistance = math.abs(countPosX - namePosX);
    local totalWidth = countLabelWidth + nameLabelWidth;

    if posDistance < totalWidth + 10 then
        self.expandWidth = math.max(self.expandWidth, (totalWidth + 10) - posDistance);
    end
end

-- 工坊工人信息适配语言版本（背景宽，scrollview的宽）
function UINewWorkshop:updateWorkshopWidth()
    self:updateFoldConfig();

    if self.expandWidth <= 0 then
        return;
    end

    for _, child in pairs(self.workshopChildren) do
        local nameLabel = child:getChildByName("name");
        local countLabel = child:getChildByName("count");

        nameLabel:setPositionX(nameLabel:getPositionX() - self.expandWidth / 2);
        countLabel:setPositionX(countLabel:getPositionX() + self.expandWidth / 2);

        child:setPositionX(child:getPositionX() + self.expandWidth/ 2);
    end
end

-- 初始化引导相关
function UINewWorkshop:initGuide()
    -- 开始生产
    self:startProduce();

    -- 工匠招募引导已完成
    if AlchemyWorkshopM.isGuideFinished(5) then
        local totalNum = math.min(AlchemyWorkshopM.getTotalWorkerNum(), 10);
        for i = 1, totalNum do
            self:workerRunIn(false);
        end
    end

    -- 引导是否全部完成
    if AlchemyWorkshopM.isAllGuideFinished() then
        self.waitForClick = false;
        return;
    end

    -- 第一步引导还未完成
    if not AlchemyWorkshopM.isGuideFinished(1) then
        -- 只显示金币条，从右边飞入
        UIMgr.getCurrentScene().topMenu:moneyBarFlyIn();
    else
        self.waitForClick = false;
        UIMgr.getCurrentScene().topMenu:showMoneyBar();
    end

    -- 工匠招募引导已完成
    if AlchemyWorkshopM.isGuideFinished(4) then
        UIMgr.getCurrentScene().topMenu:showMoneyBarAndWorkerBar();
    end

    -- 隐藏标题栏、设置、返回按钮
    local btnBack = findChildByName(self.node,"BT/btn_back");
    btnBack:setVisible(false);
    if SKIP_WORKSHOP_GUIDE == 1 then
        btnBack:setVisible(true);
    end

    local btnSetting = findChildByName(self.node,"BT/setting");
    if AlchemyWorkshopM.getTotalWorkerNum() == 0 then
        btnSetting:setVisible(false);
    end

    -- 冈布奥
    local slime = findChildByName(self.node, "bg/slime");
    local slimeIcon = findChildByName(self.node, "bg/slime/icon");
    local slimeShadow = findChildByName(self.node, "bg/slime/shadow");
    slimeIcon:loadTexture("images/ui/workshop/new_slime.png", 1);
    slimeShadow:loadTexture("images/ui/workshop/shadow2.png", 1);

    slime:setVisible(true);
    local function jump()
        local action1 = cc.CallFunc:create(function()
            slimeIcon:setScaleX(1.2);
        end);
        local jumpTo = cc.JumpBy:create(0.4, cc.p(30, 0), 20, 2);
        local jumpTo2 = cc.JumpBy:create(0.4, cc.p(30, 0), 0, 2);
        local delay = cc.DelayTime:create(0.5);
        local action2 = cc.CallFunc:create(function()
            slimeIcon:setScaleX(-1.2);
        end);
        local jumpBack = cc.JumpBy:create(0.4, cc.p(-30, 0), 20, 2);
        local jumpBack2 = cc.JumpBy:create(0.4, cc.p(-30, 0), 0, 2);
        local callFunc = cc.CallFunc:create(function()
            local t = math.random(2, 5);
            performWithDelay(slime, jump, t);
        end);

        slimeIcon:runAction(cc.Sequence:create(action1, jumpTo, delay, action2, jumpBack, callFunc));
        slimeShadow:runAction(cc.Sequence:create(action1, jumpTo2, delay, action2, jumpBack2));
    end
    performWithDelay(slime, jump, 0.5);
end

-- 炼金炉开始工作
function UINewWorkshop:startProduce()
    local produceNode = findChildByName(self.node, "bg/produce_node");
    local flowNode = findChildByName(self.node, "bg/flow_node");
    -- 金水流淌
    playEffect(flowNode, 1174, 0, 0);

    local furnaceIcon = findChildByName(self.node, "bg/furnace_icon");

    -- 金币位置列表
    self.goldPosList = {};
    for i = 1, 20 do
        local posNode = findChildByName(self.node, "bg/pos_parent/pos"..i);
        local jump2Node = posNode:getChildByName("jump2");
        local jump1Node = posNode:getChildByName("jump1");
        posNode.offset1 = cc.p(jump1Node:getPosition());
        posNode.offset2 = cc.p(jump2Node:getPosition());

        posNode:setLocalZOrder(math.floor(-posNode:getPositionY()));
        table.insert(self.goldPosList, posNode);
    end

    -- 工人位置表
    self.workerPosList = {};
    for i = 1, 10 do
        local posNode = findChildByName(self.node, "bg/pos_parent/worker"..i);
        posNode:setLocalZOrder(math.floor(-posNode:getPositionY()));
        posNode:setTag(i);
        table.insert(self.workerPosList, posNode);
    end

    table.randomSort(self.goldPosList);
    table.randomSort(self.workerPosList);

    self.slimeIconList = self:getSlimeIconList();

    self.slimes = {};
    self.shadows = {};

    local bubble = findChildByName(self.node, "bg/bubble");

    -- 炼金
    local function start()
        if self.waitForClick or self:getFreePos() == nil or self.isHighlightWorkshopBubble
            or (not AlchemyWorkshopM.isAllGuideFinished() and bubble:isVisible()) then
            produceNode:removeAllChildren();
            performWithDelay(self, start, 0.5);
            return;
        end

        furnaceIcon:setVisible(false);

        -- 喷金币
        produceNode:removeAllChildren();
        playEffect(produceNode, 1173, 88, -53);

--        performWithDelay(produceNode, function() AudioM.playFx("workshop_furnance"); end, 0.1);
--        performWithDelay(produceNode, function() AudioM.playFx("workshop_produce"); end, 2.3);

        local function produce()
            furnaceIcon:setVisible(true);

            local produceCountEachTime = FormulaM.invoke("GET_GOLD_PRODUCE_AMOUNT");
            self:produceGold(produceCountEachTime);

            performWithDelay(self, start, 0.6);
        end
        performWithDelay(self, produce, 2);
    end

    start();
end

-- 获取空闲位置
function UINewWorkshop:getFreePos()
    -- 引导未完成期间，最多喷十个
    if not AlchemyWorkshopM.isAllGuideFinished() then
        local usedCount = 0;
        for _, node in pairs(self.goldPosList) do
            if node.isUsed then
                usedCount = usedCount + 1;
            end
        end
        if usedCount >= 10 then
            return nil;
        end
    end

    for _, node in pairs(self.goldPosList) do
        if not node.isUsed then
            return node;
        end
    end

    return nil;
end

-- 炼金炉喷出金子
function UINewWorkshop:produceGold(count)
    if self.waitForClick == true then
        return;
    end

    local goldNode = findChildByName(self.node, "bg/gold_node");
    local goldParentNode = findChildByName(self.node, "bg");

    for i = 1, count do
        local newGold = goldNode:clone();
        newGold:setVisible(true);
        local gold = newGold:getChildByName("gold");
        gold:setVisible(true);
        local shadow = newGold:getChildByName("shadow");

        local targetNode = self:getFreePos();
        if targetNode == nil then
            -- 没有空闲位置，就不产了
            return;
        end

        local targetPos = cc.p(targetNode:getPosition());

        targetNode.isUsed = true;

        local jumpTo1 = cc.JumpTo:create(0.2, cc.pAdd(targetPos, targetNode.offset2), 50, 1);
        local jumpTo2 = cc.JumpTo:create(0.1, cc.pAdd(targetPos, targetNode.offset1), 10, 1);
        local jumpTo3 = cc.JumpTo:create(0.1, targetPos, 5, 1);
        local callFunc = cc.CallFunc:create(function()
            goldParentNode:removeChild(newGold);
            newGold:setPosition(0, 0);

            shadow:setVisible(true);

            -- 到目标节点后，从底图删除，挂在目标节点上
            targetNode:removeAllChildren();
            targetNode:addChild(newGold);
            targetNode:setVisible(true);

            local function showGoldEffect()
                local effect;
                local callFunc1 = cc.CallFunc:create(function()
                    local gold = newGold:getChildByName("gold");
                    gold:setOpacity(10);
                    shadow:setOpacity(0);

                    -- 播放金币闪过的动画
                    _, effect = playEffect(newGold, 1161, 2, -13);
                end);
                local delay = cc.DelayTime:create(1);
                local callFunc2 = cc.CallFunc:create(function()
                    newGold:removeChild(effect);

                    -- 动画播放完毕，金币图标出现
                    gold:setOpacity(255);
                    shadow:setOpacity(255);

                    performWithDelay(newGold, showGoldEffect, math.random(3, 10));
                end);
                newGold:runAction(cc.Sequence:create(callFunc1, delay, callFunc2));
            end
            showGoldEffect();

            -- 第一块金币，引导玩家去捡
            if self.waitForClick == nil then
                self.waitForClick = true;
                local hand = newGold:getChildByName("hand");
                hand:setVisible(true);
                hand:setLocalZOrder(1000);
                playClickEffect(hand);
            end

            -- 一次喷两个金币，引导玩家拖动
            if self.showDragEffect and i == 1 then
                self.showDragEffect = false;
                self.waitForClick = true;
                local hand = newGold:getChildByName("hand");
                hand:removeAllChildren();
                playDragEffect(hand);
            end
        end);

        newGold:runAction(cc.Sequence:create(jumpTo1, jumpTo2, jumpTo3, callFunc));
        -- 先在底图上飞
        goldParentNode:addChild(newGold);
    end

    if self.lastCount == 1 and count == 2 then
        self.showDragEffect = true;
    end

    self.lastCount = count;
end

-- 检查是否触碰到其他金币
function UINewWorkshop:tryPickupGold(movePos)
    for _, node in pairs(self.goldPosList) do
        if node.isUsed then
            local panel = findChildByName(node, "gold_node/panel");
            if panel then
                local pos =  node:convertToWorldSpaceAR(cc.p(-10, -10));
                local size = panel:getContentSize();
                local rect = cc.rect(pos.x - size.width / 2, pos.y - size.height / 2, size.width, size.height);

                if cc.rectContainsPoint(rect, movePos) then
                    self:pickupGold(node);
                    return;
                end

                local lt = cc.p(rect.x, rect.y + rect.height);
                local rt = cc.p(rect.x + rect.width, rect.y + rect.height);
                local lb = cc.p(rect.x, rect.y);
                local rb = cc.p(rect.x + rect.width, rect.y);

                -- 判断移动的两个点组成的线段和四边行的边是否相交，解决滑动过快无法捡取金币的问题
                if self.lastMovePos ~= nil then
                   if cc.pIsSegmentIntersect(self.lastMovePos, movePos, lt, rt)
                        or cc.pIsSegmentIntersect(self.lastMovePos, movePos, rt, rb)
                        or cc.pIsSegmentIntersect(self.lastMovePos, movePos, rb, lb)
                        or cc.pIsSegmentIntersect(self.lastMovePos, movePos, lb, lt) then
                        self:pickupGold(node);
                        return;
                   end
                end
            end
        end
    end

    self.lastMovePos = cc.p(movePos.x, movePos.y);
end

-- 拾取金币
function UINewWorkshop:addGold()
    local cur_money = ME.user.dbase:query("money") or 0;
    local max_money = FormulaM.invoke("CALC_USER_MAX_MONEY", ME.user);

    if cur_money < max_money then
        -- 本地先加上
        ME.user:addAttrib("money", 1, "workshop");
    end

    -- 检测金币是否到达采集上限
    AlchemyWorkshopM.checkMoneyLimit();

    -- 累加
    self.pickUpGolds = self.pickUpGolds or 0;
    self.pickUpGolds = self.pickUpGolds + 1;

    local function sync()
        Operation.cmd_pickup_workshop_gold(self.pickUpGolds);
        self.pickUpGolds = 0;
    end
    self.bg:stopAllActions();
    performWithDelay(self.bg, sync, 0.5);
end

-- 捡起金币
function UINewWorkshop:pickupGold(targetNode)
    -- 随机播放一个音效
    AudioM.playFx("pick_money_"..tostring(math.random(5)));

    local function callback()
        -- 回调回来可能窗口已经关闭，需要做下nil判断
        if self ~= nil and self.addGold ~= nil then
            self:addGold();
        end
    end

    -- 拾取物品
    --alert(getLocStr("add_one_gold"));
    self:goldFlyTo(targetNode, callback);

    self.waitForClick = false;
    targetNode.isUsed = false;
    targetNode:stopAllActions();
    targetNode:removeAllChildren();
end

-- 物品往金币栏上飞
function UINewWorkshop:goldFlyTo(targetNode, callback)
    -- 捡取的金币坐标
    local originPos =  targetNode:convertToWorldSpaceAR(cc.p(-20, -10));

    -- 引导是否全部完成
    local iconNode = UIMgr:getCurrentScene().topMenu:getMoneyIconNode();
    local textNode = UIMgr:getCurrentScene().topMenu:getMoneyTextNode();

    -- 捡取的金币坐标转成目标节点的坐标
    local parentNode = iconNode:getParent();
    local fromPos = parentNode:convertToNodeSpace(originPos);
    local toPos = cc.pAdd(cc.p(iconNode:getPosition()), cc.p(-30, 0));

    local duration = math.max(cc.pGetDistance(fromPos, toPos), 400) / 800;

    local icon = ccui.ImageView:create();
    icon:loadTexture("images/ui/workshop/guide/gold.png");
    icon:setPosition(fromPos);
    icon:setScale(0.5);
    icon:setLocalZOrder(10000);

    local callfunc = cc.CallFunc:create(function()
        iconNode:removeChild(icon);

        local callFunc1 = cc.CallFunc:create(function()
            setHighLightMode(iconNode, true);
        end);
        local delay = cc.DelayTime:create(0.2);
        local callFunc2 = cc.CallFunc:create(function()
            setHighLightMode(iconNode, false);
        end);

        iconNode:runAction(cc.Sequence:create(callFunc1, delay, callFunc2));

        -- 文字变大特效
        local oldAnchorPoint = UIMgr:getCurrentScene().topMenu:getMoneyTextNodeAnchorPoint();
        local oldPosition = UIMgr:getCurrentScene().topMenu:getMoneyTextNodePos();
        commonTextEffect(textNode, nil, oldAnchorPoint, oldPosition);

        if callback then
            callback();
        end

    end);

    local moveTo = cc.EaseInOut:create(cc.MoveTo:create(duration, toPos), 2.0);
    local rotate = cc.RotateBy:create(duration, 360);
    local scaleTo = cc.ScaleTo:create(duration, 0.3);
    icon:runAction(cc.Sequence:create( cc.Spawn:create(moveTo, rotate, scaleTo), callfunc));
    iconNode:addChild(icon);
end

-- 检查引导进度
function UINewWorkshop:checkGuide()
    if AlchemyWorkshopM.isAllGuideFinished() then
        return;
    end

    -- 先直接强行引导, 后面考虑统一流程TODO
    local nextGuideId = AlchemyWorkshopM.getNextWorkshopGuideId();
    if nextGuideId == nil then
        return;
    end

    -- 如果已经配置了10个工匠，直接跳到购买装备引导
    if self:getWorkingNum() >= 10 and nextGuideId < 7 then
        for id = 5, 6 do
            if not AlchemyWorkshopM.isGuideFinished(id) then
                Operation.cmd_set_workshop_guide_progress(id);
            end
        end

        nextGuideId = 7;
    end

    self:startGuide(nextGuideId);
end

-- 设置引导进度
function UINewWorkshop:startGuide(id)
    if id >= 1 and id <= 3 then
        self:guideToStrengthen(id);
    elseif id == 4  then
        self:guideToRecruit(id);
    elseif id == 5 then
        self:checkConfigProgress(id);
    elseif id == 6 then
        self:guideToRecruit2(id);
    elseif id == 7 then
        self:checkConfigProgress(id);
    elseif id == 8 then
        self:guideToStartAdventure(id);
    end
end

-- 设置燃料强化进度
function UINewWorkshop:guideToStrengthen(id)
    local requireItemId = 1;
    local requireLevels = {1, 2, 3};

    local level = AlchemyWorkshopM.getStrengthenLevel(requireItemId);
    if level >= requireLevels[id] then
        Operation.cmd_set_workshop_guide_progress(id);

        -- 等级达到三级时，slime说话
        if level == 3 then
            local function talk()
                local recruitLevel = AlchemyWorkshopM.getStrengthenLevel(2);
                local msg = getLocStr("i_need_workers");
                if recruitLevel > 0 then
                    msg = getLocStr("i_need_workers2");
                end
                self:slimeTalk(msg);
            end
            performWithDelay(self, talk, 6.5);
        end
    end
end

-- 招募工匠进度
function UINewWorkshop:guideToRecruit(id)
    if self.isGuideProgressing then
        return;
    end

    local requireItemId = 2;
    local requireLevel = 1;

    local level = AlchemyWorkshopM.getStrengthenLevel(requireItemId);
    if level < requireLevel then
        return;
    end

    -- 招募完成，设置指引进度
    Operation.cmd_set_workshop_guide_progress(id);

    EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);
    EventMgr.register("UINewWorkshop", event.REMOVE_FORM, function(params)
        local name = params["name"];
        print("removeForm:"..name);
        if name == "UIWorkshopStrengthen" then
            self.backGuideDone = false;
            self.isGuideProgressing = false;

            if level >= requireLevel then
                local delay1 = cc.DelayTime:create(2);

                -- 显示工人条，从右边飞入
                local action2 = cc.CallFunc:create(function()
                    UIMgr.getCurrentScene().topMenu:workerBarFlyIn();

                end);

                -- 配置按钮、标题栏出现
                local delay2 = cc.DelayTime:create(1);
                local action3 = cc.CallFunc:create(function()
                    self:showTitleAndConfig();
                end);

                self:runAction(cc.Sequence:create(action1, delay1, action2, delay2, action3));

                EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);
            end
        end
    end);

    self.isGuideProgressing = true;
end

-- 招募工匠进度
function UINewWorkshop:guideToRecruit2(id)
    if self.isGuideProgressing then
        return;
    end

    local requireItemId = 2;
    local requireLevel = 2;

    local level = AlchemyWorkshopM.getStrengthenLevel(requireItemId);
    if level < requireLevel then
        return;
    end

    -- 招募完成，设置指引进度
    Operation.cmd_set_workshop_guide_progress(id);

    EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);
    EventMgr.register("UINewWorkshop", event.REMOVE_FORM, function(params)
        local name = params["name"];
        print("removeForm:"..name);
        if name == "UIWorkshopStrengthen" then
            self.isGuideProgressing = false;

            if level >= requireLevel then
                EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);

                local idleNum = AlchemyWorkshopM.getIdleWorkerNum();
                if idleNum >= 5 then
                    self:showTitleAndConfig();
                end
            end
        end
    end);

    self.isGuideProgressing = true;
end

-- 获取空闲的工人位置
function UINewWorkshop:getFreeWorkerPos()
    for _, node in pairs(self.workerPosList) do
        if not node.isUsed then
            return node;
        end
    end

    return nil;
end

-- 获取正在工作的工人数
function UINewWorkshop:getWorkingNum()
    local count = 0;
    for _, node in pairs(self.workerPosList) do
        if node.isUsed then
            count = count + 1;
        end
    end

    return count;
end

-- 随机slime工人图标
function UINewWorkshop:getSlimeIconList()
    local iconList = {};

    local default = "images/ui/workshop/new_slime.png";
    local worker1 = "images/ui/workshop/worker1.png";
    local worker2 = "images/ui/workshop/worker2.png";
    local worker3 = "images/ui/workshop/worker3.png";

    for i = 1, 7 do
        table.insert(iconList, default);
    end

    table.insert(iconList, worker1);
    table.insert(iconList, worker2);
    table.insert(iconList, worker3);

    table.randomSort(iconList);
    return iconList;
end

-- 奖励物品飞入特效
function UINewWorkshop:playItemsFlyIn(bonusList)
    if #bonusList == 0 then
        return;
    end

    local storeNode = findChildByName(self.node, "bg/store_icon");
    local posParent = findChildByName(self.node, "bottom/pos_parent");

    if storeNode.gainItemList == nil then
        storeNode.gainItemList = {};
    end

    -- 目标位置先转成世界坐标
    local worldPos = storeNode:convertToWorldSpaceAR(cc.p(0, 0));

    -- 再转到相对于sourceNode的父节点的坐标
    local parentNode = posParent:getParent();
    local toPos = parentNode:convertToNodeSpace(worldPos);
    local fromPos = cc.p(posParent:getPositionX() + 5, posParent:getPositionY() + 25);

    for i = 1, #bonusList do
        local classId = bonusList[i]["class_id"];
        local num = bonusList[i]["count"] * bonusList[i]["times"];
        local prop;
        local iconPath;
        local name;

        if type(classId) == "number" then
            -- 加成，只管食材
            if ItemM.isFoodMaterial(classId) then
                prop = PropM.combine(ME.user, "scout_bonus", "food_material");
                num = PropM.apply(prop, num);
            end
            iconPath = getItemIconPath(ItemM.query(classId, "icon"));
            name = ItemM.query(classId, "name");
        elseif classId == "gem" then
            iconPath = getItemIconPath(9999);
            name = FieldsM.getFieldName("gem");
        elseif classId == "money" then
            -- 加成
            prop = PropM.combine(ME.user, "scout_bonus", classId);
            num =  PropM.apply(prop, num);

            local unit = bonusList[i]["count"] / ScoutM.getScoutCount();
            if unit == 1000 then
                classId = 1509;
            elseif unit == 200 then
                classId = 1508;
            else
                classId = 1507;
            end
            -- 金币
            iconPath = getItemIconPath(ItemM.query(classId, "icon"));
            name = getLocStr("money");
        end

        local notifyText = string.format(getLocStr("gain_scout_items"), name, num);
        table.insert(storeNode.gainItemList, notifyText);

        local function callback()
            -- 仓库图标闪一下
            playEffect(storeNode, 1236, 115, 68);
        end

        local function effectPlay()
            scoutItemsFlyTo(parentNode, fromPos, toPos, iconPath, 1, callback);
        end

        -- 加2.5秒是等斥候先跑进来
        performWithDelay(self.node, effectPlay, i * 0.5 + 1.9);
    end

    local function createTextFunc(color, str)
        local text = ccui.Text:create();
        text:setFontName(getLocFontName());
        text:setFontSize(36);
        text:setString(str);
        text:setTextColor(color);
        text:setAnchorPoint(cc.p(0.5, 0.5));
        local outlineColor = TextStyleM.TEXT_COLOR_DARK_BROWN;
        text:enableOutline(cc.c4b(outlineColor[1], outlineColor[2], outlineColor[3], 255), 2);
        text:enableShadow(TextStyleM.TEXT_OUTLINE_COLOR_DARK, cc.size(3, -3));
        text:getVirtualRenderer():setAdditionalKerning(getLocKerning() -4);
        --text:setScale(0.8);
        return text;
    end

    local function showName()
        showItemName(storeNode, TextStyleM.TEXT_COLOR_BRIGHT_YELLOW, 70, storeNode:getContentSize().height + 6, createTextFunc);
    end

    performWithDelay(self.node, showName, 0.5 + 1.9);

    local function callBack()
        self:removeScout();
        self.isPlayScoutEffect = false;

        -- 去掉蒙版
        local mask = findChildByName(self.node, "mask");
        mask:setVisible(false);

        -- 按钮恢复
        local btnScout = findChildByName(self.node, "BT/scout");
        btnScout:setTouchEnabled(true);
        btnScout:setBright(true);

        -- 显示泡泡
        local hintNode =  findChildByName(btnScout, "hint");
        checkBlueBubbleStatus(hintNode, true);

        -- 斥候动画
        self:scoutJump(ScoutM.getScoutCount());
    end

    -- 开始播放跳跃动画
    performWithDelay(self.node, callBack, (#bonusList + 1) * 0.5 + 4);
end

-- 清除斥候冈布奥
function UINewWorkshop:removeScout()
    local posParent = findChildByName(self.node, "bottom/pos_parent");
    posParent:stopAllActions();
    -- 清空
    for i = 1, #shadowList do
        posParent:removeChild(shadowList[i]);
        posParent:removeChild(slimeList[i]);
    end
    shadowList = {};
    slimeList = {};
end

-- 斥候冈布奥跳动
function UINewWorkshop:scoutJump(showNum)
    local posParent = findChildByName(self.node, "bottom/pos_parent");
    posParent:stopAllActions();

    if showNum > 3 then
        showNum = 3;
    end

    if showNum == #slimeList then
        -- 数量没变,不用修改
        return;
    end

    -- 探索界面还开着先不播放
    local uiScoutInfo =  UIMgr.getCurrentScene():getFormByName("UIScoutInfo");
    if uiScoutInfo ~= nil then
        return;
    end

    -- 先清空
    for i = 1, #shadowList do
        posParent:removeChild(shadowList[i]);
        posParent:removeChild(slimeList[i]);
    end
    shadowList = {};
    slimeList = {};

    -- 加载合图
    cc.SpriteFrameCache:getInstance():addSpriteFrames("images/ui/workshop_workers.plist");

    -- 先创建阴影,保证所有阴影在冈布奥后面
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(i));
        local shadow = ccui.ImageView:create();
        shadowList[i] = shadow;
        shadow:setScale(0.8);
        posParent:addChild(shadow);
        shadow:setPosition(cc.p(pos:getPositionX() + shadowOffset[i], pos:getPositionY() + 2));
        shadow:loadTexture("images/ui/workshop/shadow2.png", 1);
        shadow:setVisible(true);
    end

    -- 创建冈布奥
    for i = 1, showNum do
        local pos = posParent:getChildByName("pos" .. tostring(showNum - i + 1));
        local slime = ccui.ImageView:create();
        slimeList[i] = slime;
        posParent:addChild(slime);
        slime:setPosition(pos:getPosition());
        slime:loadTexture(getScoutIconPath(showNum - i + 1));
        local posX = slime:getPositionX();
        local posY = slime:getPositionY();

        -- 把锚点设置为下底边中心
        slime:setAnchorPoint(cc.p(0.5, 0));
        local function jump()
            -- 获取随机种子
            local jumps = math.ceil(math.random(2, 5));
            local height = math.random(5, 15);
            local r = math.random(300, 800);

            -- 时间基数
            local TIME_BASE = 0.35;
            -- 最大压缩量
            local MAX_COMPRESS_VALUE = 0.1;
            -- 计算压缩因子
            local ScaleFactor = MAX_COMPRESS_VALUE * height / 15;
            -- 把锚点设置为下底边中心
            slime:setAnchorPoint(cc.p(0.5, 0));
            -- 压缩
            local compressDown1 = cc.EaseIn:create(cc.ScaleTo:create(0.05, 1, 1-ScaleFactor), 2.5);
            -- 拉伸
            local stretchUp1 = cc.EaseOut:create(cc.ScaleTo:create(0.05, 1, 1+ScaleFactor), 2.5);
            -- 起跳
            local jumpBy = cc.JumpTo:create(TIME_BASE*height/15, cc.p(posX, posY), height, 1);
            -- 压缩
            local compressDown2 = cc.EaseOut:create(cc.ScaleTo:create(0.05, 1, 0.8), 2.5);
            -- 拉伸还原
            local stretchUp2 = cc.EaseOut:create(cc.ScaleTo:create(0.05, 1, 1), 2.5);

            -- 竖直方向上的跳跃
            slime:runAction(cc.Sequence:create(compressDown1, stretchUp1, jumpBy, compressDown2, stretchUp2));

            -- 不同斥候跳跃不同频
            performWithDelay(slime, jump, r / 100);
        end

        -- 间隔随机时间1-4秒,首次进入时少停留一会就播
        local r = math.random(50, 100);
        performWithDelay(slime, jump, r / 100);
    end
end

-- 从四面八方跑过来工匠
function UINewWorkshop:workerRunIn(firstRun)
    cc.SpriteFrameCache:getInstance():addSpriteFrames("images/ui/workshop_workers.plist");

    local bg = findChildByName(self.node, "bg");

    local freeNode = self:getFreeWorkerPos();
    if freeNode == nil then
        return;
    end
    -- 保证阴影在冈布奥后面
    local shadow = ccui.ImageView:create();
    shadow:setScale(0.8);
    freeNode:addChild(shadow);

    local slime = ccui.ImageView:create();
    slime:setScale(0.8);
    freeNode:addChild(slime);

    local toPos = cc.p(0, 0);
    freeNode.isUsed = true;

    local fromPos = cc.p(0, 0);

    local nodePosX = freeNode:getPositionX();
    if nodePosX < DESIGN_WIDTH / 2 then
        fromPos.x = - nodePosX - 100;
    else
        fromPos.x = DESIGN_WIDTH - nodePosX + 100;
    end

    if not firstRun then
        fromPos = toPos;
    end

    slime:setPosition(fromPos);
    shadow:setPosition(fromPos);

    local iconPath = self.slimeIconList[freeNode:getTag()];
    slime:loadTexture(iconPath, 1);
    shadow:loadTexture("images/ui/workshop/shadow2.png", 1);

    -- 把锚点设置为下底边中心
    slime:setAnchorPoint(cc.p(0.5, 0));

    local shadowOffset = self:getWorkerShadowOffset(iconPath);
    local targetPos = toPos;
    local origionPos = targetPos;

    local offsetX = slime:getPositionX() - targetPos.x;
    local shadowTargetPos = targetPos;
    if offsetX > 0 then
        slime:setScaleX(-0.8);
        shadow:setScaleX(-0.8);
    else
        slime:setScaleX(0.8);
        shadow:setScaleX(0.8);
    end

    freeNode:setLocalZOrder(math.floor(-freeNode:getPositionY()));
    local isFirstRun = firstRun;
    local function jump()
        local jumps = math.ceil(math.abs(offsetX) / 200);
        local height = math.random(5, 15);

        -- 计算跳跃次数
        -- 首次进入时，根据距离的不同，修正跳跃次数
        local jumpNum = math.abs(offsetX / 35);
        local times = isFirstRun and jumpNum or 1;

        -- 冈布奥待机动画
        local function idleAnimation()
            -- 判断方向(正右，负左)
            local origionPos2 = cc.p(slime:getPosition());
            local direction = (targetPos.x - origionPos2.x > 0) and 1 or -1;
            -- 最大扭曲角度
            local MAX_SKEW_DEGREE = 5;
            -- 计算扭曲因子
            local skewFactor = math.floor(MAX_SKEW_DEGREE * (targetPos.x - origionPos.x) / 20);
            -- 先转向
            local oriScale = slime:getScaleX();
            local xScale = direction*0.8;
            slime:setScale(xScale, 0.8);
            -- 右上方向扭曲
            local skewRight = cc.EaseIn:create(cc.SkewBy:create(0.05, skewFactor, 0), 2.5);
            -- 压缩
            local compressDown1 = cc.EaseIn:create(cc.ScaleTo:create(0.025, xScale, 0.7), 2.5);
            -- 拉伸
            local stretchUp1 = cc.EaseOut:create(cc.ScaleTo:create(0.05, xScale, 0.9), 2.5);
            -- 起跳
            jumps = isFirstRun and jumps or 0.2;
            local jumpBy = cc.JumpTo:create(jumps, targetPos, 13, times);
            -- 左上方向扭曲
            local skewLeft = cc.EaseOut:create(cc.SkewBy:create(0.2, -skewFactor, 0), 2.5);
            -- 压缩
            local compressDown2 = cc.EaseOut:create(cc.ScaleTo:create(0.1, xScale, 0.75), 2.5);
            -- 站直
            local skewVertical = cc.EaseOut:create(cc.SkewBy:create(0.05, 0, 0), 2.5);
            -- 拉伸还原
            local stretchUp2 = cc.EaseOut:create(cc.ScaleTo:create(0.05, xScale, 0.8), 2.5);

            -- 根据方向进行跳跃
            slime:stopAllActions();
            if targetPos.x - origionPos.x > 0 then
                slime:runAction(cc.Sequence:create(compressDown1, skewRight, stretchUp1, jumpBy, compressDown2, skewLeft, stretchUp2, skewVertical));
            else
                slime:runAction(cc.Sequence:create(compressDown1, skewLeft, stretchUp1, jumpBy, compressDown2, skewRight, stretchUp2, skewVertical));
            end

            -- 影子位置
            shadowTargetPos = targetPos;
            if shadowOffset then
                if oriScale * direction < 0 then
                    -- 转向了
                    shadow:setPositionX(shadow:getPositionX() - 2 * direction * shadowOffset[1]);
                end
                if direction > 0 then
                    shadowTargetPos.x = targetPos.x - shadowOffset[1];
                else
                    shadowTargetPos.x = targetPos.x + shadowOffset[1];
                end
            end
        end
        idleAnimation();

        local jumpBy2 = cc.JumpTo:create(jumps, cc.p(shadowTargetPos.x , shadowTargetPos.y - 1), 0, times);
        shadow:stopAllActions();
        shadow:runAction(cc.Sequence:create(cc.DelayTime:create(0.3), jumpBy2));

        isFirstRun = false;

        -- 间隔随机时间2-8秒
        local r = math.random(200, 800);
        local x = math.random(-10, 10);
        local y = math.random(10, 10);
        origionPos = targetPos;
        targetPos = cc.pAdd(toPos, cc.p(x, y));
        performWithDelay(slime, jump, r / 100);
    end

    -- 间隔随机时间1-4秒,首次进入时少停留一会就播
    local r = math.random(50, 150);
    performWithDelay(slime, jump, r / 100);

end

-- 显示标题栏和配置按钮
function UINewWorkshop:showTitleAndConfig(id)
    self.waitForClick = true;

    -- 显示标题栏、设置、返回按钮
    local btnSetting = findChildByName(self.node,"BT/setting");
    btnSetting:setVisible(true);

    -- 引导玩家进行配置
    if SKIP_WORKSHOP_GUIDE ~= 1 then

        -- 把所有可能打开的界面关闭
        UIMgr.getCurrentScene():removeFormByName("UISystemSetting");
        UIMgr.getCurrentScene():removeFormByName("UIErrorInfo");
        UIMgr.getCurrentScene():removeFormByName("UIGD");
        UIMgr.getCurrentScene():removeFormByName("UIWorkshopStrengthen");
        UIMgr.getCurrentScene():removeFormByName("UIStrengthenDetail");

        local uiGuide = UIGuideMask.create(self, "BT/setting", 70, 0);
        UIMgr.getCurrentScene():addForm(uiGuide);

        self.addWorkerCount = 0;
        self.backGuideDone = false;

        -- 注册窗口回调
        EventMgr.register("UINewWorkshop", event.ADD_FORM, function(params)
            local name = params["name"];
            print("addFrom:"..name);
            if name == "UIWorkshopConfig" then
                local form = UIMgr.getCurrentScene():getFormByName(name);
                if form ~= nil then
                    local uiGuide = UIGuideMask.create(form, "TOP/scrollview/item1/btn_add");
                    UIMgr.getCurrentScene():addForm(uiGuide);
                    EventMgr.remove("UINewWorkshop", event.ADD_FORM);
                end
            end
        end);

        EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);
        EventMgr.register("UINewWorkshop", event.REMOVE_FORM, function(params)
            local name = params["name"];
            print("removeForm:"..name);
            if name == "UIGuideMask" and self.addWorkerCount < 4 then
                local form = UIMgr.getCurrentScene():getFormByName("UIWorkshopConfig");
                if form ~= nil then
                    local uiGuide = UIGuideMask.create(form, "TOP/scrollview/item1/btn_add");
                    UIMgr.getCurrentScene():addForm(uiGuide);
                    self.addWorkerCount = self.addWorkerCount + 1;
                end
            elseif name == "UIGuideMask" and not self.backGuideDone then
                local form = UIMgr.getCurrentScene():getFormByName("UIWorkshopConfig");
                if form ~= nil then
                    local uiGuide = UIGuideMask.create(form, "BT/ok", -70, 0, true);
                    UIMgr.getCurrentScene():addForm(uiGuide);
                    self.backGuideDone = true;
                end
            elseif name == "UIWorkshopConfig" then
                EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);

                self.backGuideDone = false;
                self.addWorkerCount = 0;
                self.waitForClick = false;
                print("self.waitForClick set to false");
            end
        end);
    end
end

-- 配置工匠进度
function UINewWorkshop:checkConfigProgress(id)
    local idleNum = AlchemyWorkshopM.getIdleWorkerNum();
    local totalNum = AlchemyWorkshopM.getTotalWorkerNum();

    -- 配置5工匠
    if id == 5 and totalNum >= 5 and (totalNum - idleNum) >= 5 then
        Operation.cmd_set_workshop_guide_progress(id);
    end

    -- 配置10个工匠后，引导出工坊去冒险
    if id == 7 and totalNum >= 10 and (totalNum - idleNum) >= 10 then
        Operation.cmd_set_workshop_guide_progress(id);
        self:guideToStartAdventure(id + 1);
    end
end

-- 显示购买装备的泡泡
function UINewWorkshop:showBuyEquipBubble()
    local amount = FormulaM.invoke("GET_WORKSHOP_BUY_EQUIP_PRICE", ME.user);
    local curMoney = ME.user.dbase:query("money", 0);

    local bubble = findChildByName(self.node, "bg/slime/bubble");
    if not self.isShowBuyEquipBubble then
        local function delay()
            -- 冈布奥说话
            self:slimeTalk(getLocStr("guide_slime_talk1"));

            local bg = findChildByName(self.node, "bg");
            local scaleX = bg:getScaleX();

            local function response2()
                local wordsNode = findChildByName(self.node, "bg/words_node_4");
                wordsNode:setScale(1.2);
                createWordsFrame(wordsNode, getLocStr("guide_slime_response2"), WORDS_FRAME_ARROW_BOTTOM_LEFT, 3.5, 0.01);

                local function delay()
                    if curMoney >= amount then
                        -- 显示购买装备的蒙版
                        self:highlightBuyEquipBubble();
                    else
                        local guideMask = findChildByName(self.node, "guide_mask");
                        guideMask:setVisible(false);

                        bubble:setVisible(true);
                        bubble:setScale(0.2);
                        local scale1 = cc.ScaleTo:create(0.2, 1.5);
                        local scale2 = cc.ScaleTo:create(0.1, 1.1);
                        local scale3 = cc.ScaleTo:create(0.1, 1.3);
                        local scale4 = cc.ScaleTo:create(0.1, 1);
                        local delay = cc.DelayTime:create(0.1);
                        local callFunc2 = cc.CallFunc:create(function()
                            playBubbleAnima(bubble, true);
                        end);
                        bubble:runAction(cc.Sequence:create(scale1, scale2, scale3, scale4, delay, callFunc2));
                    end
                end
                performWithDelay(self, delay, 4.5);
            end

            local function response()
                local wordsNode = findChildByName(self.node, "bg/words_node_1");
                wordsNode:setScale(1.2);
                createWordsFrame(wordsNode, getLocStr("guide_slime_response1"), WORDS_FRAME_ARROW_BOTTOM_LEFT, 4, 0.01);

                performWithDelay(self, response2, 0.6);
            end
            performWithDelay(self, response, 1.2);
        end

        performWithDelay(self, delay, 3);

        self.isShowBuyEquipBubble = true;
    end

    if bubble:isVisible() and curMoney >= amount then
        -- 显示购买装备的蒙版
        self:highlightBuyEquipBubble();
    end

end

-- 引导出工坊去迷宫探险
function UINewWorkshop:guideToStartAdventure(id)
    if SKIP_WORKSHOP_GUIDE == 1 then
        return;
    end

    if self.isGuideProgressing then
        return;
    end

    -- 显示盾牌泡泡
    self.checkBuyEquipBubble = true;
    self:showBuyEquipBubble();

    local slimeNode = findChildByName(self.node, "bg/slime");
    slimeNode:setVisible(true);

    local slime = findChildByName(self.node, "bg/slime/icon");
    local shadow = findChildByName(self.node,"bg/slime/shadow");

    local equip = findChildByName(self.node, "bg/slime/bubble/bg");
    equip:addTouchEventListener(function(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            local uiForm = UIGuideBuyEquip:create();
            UIMgr.getCurrentScene():addForm(uiForm);
            -- 音效
            AudioM.playFx("ui_open1");
            return;
        elseif  eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            self.lastMovePos =  sender:getTouchBeganPosition();
            self:tryPickupGold(movePos)
        end
    end);

    EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);
    EventMgr.register("UINewWorkshop", event.REMOVE_FORM, function(params)
        local name = params["name"];
        print("removeForm:"..name);
        if name == "UIHeroDetailInfo" then
            EventMgr.remove("UINewWorkshop", event.REMOVE_FORM);

            -- 还原泡泡蒙版
            self:restoreBuyEquipBubble();

            local mask = findChildByName(self.node, "mask");
            mask:setVisible(true);
            mask:setOpacity(0);

            slime:loadTexture("images/hero/1.png");
            shadow:setVisible(false);
            slimeNode:stopAllActions();
            slime:stopAllActions();
            local oldScale = slime:getScaleX();
            if oldScale > 0 then
                slime:setScaleX(-1 * oldScale);
            end
            slime:setLocalZOrder(1000);
            local bubble = findChildByName(self.node, "bg/slime/bubble");
            bubble:setVisible(false);
            self.checkBuyEquipBubble = false;

            -- 显示头像，从左边飞入
            local delay1 = cc.DelayTime:create(1);
            local showHead = cc.CallFunc:create(function()
                UIMgr.getCurrentScene().topMenu:headFlyIn();
            end);
            local delay2 = cc.DelayTime:create(1);
            local jumpOut = cc.JumpTo:create(2, cc.p(600, slime:getPositionY()), 30, 10);
            local callFunc = cc.CallFunc:create(function()
                local fadeIn = cc.FadeIn:create(1);
                local remove = cc.CallFunc:create(function()
                    UIMgr.getCurrentScene():removeFormByName("UINewWorkshop");
                    self.isGuideProgressing = false;

                    -- 设置指引步骤
                    Operation.cmd_set_workshop_guide_progress(id + 1);

                    -- 出现世界地图动画
                    UIMgr.getCurrentScene().mainMap:playEffect();

                    UIMgr.getCurrentScene().mainMap:playSlimeAnimation();
                end);
                mask:runAction(cc.Sequence:create(fadeIn, remove));
            end);

            performWithDelay(self, function() AudioM.playFx("slime_jump"); end, 1.9);
            performWithDelay(self, function() AudioM.playFx("slime_jump1"); end, 2.3);
            performWithDelay(self, function() AudioM.playFx("slime_jump1"); end, 2.7);
            slime:runAction(cc.Sequence:create(delay1, showHead, delay2, jumpOut, callFunc));
        end
    end);

    self.isGuideProgressing = true;
end

-- 停止特效
function UINewWorkshop:stopEffect()
    local bg = findChildByName(self.node, "bg");
    local BT = findChildByName(self.node, "BT");
    local bottom = findChildByName(self.node, "bottom");

    pauseNode(bg);
    pauseNode(BT);
    pauseNode(bottom);
end

-- 继续特效
function UINewWorkshop:resumeEffect()
    local bg = findChildByName(self.node, "bg");
    local BT = findChildByName(self.node, "BT");
    local bottom = findChildByName(self.node, "bottom");

    resumeNode(bg);
    resumeNode(BT);
    resumeNode(bottom);
end

-- 隐藏底部菜单
function UINewWorkshop:hideBottomMenu()
    -- 隐藏底部
    local BT = self.node:getChildByName("BT");
    local bottom = findChildByName(self.node, "bottom");
    BT:setVisible(false);
    bottom:setVisible(false);

    -- 隐藏并停止金币产出
    self.waitForClick = true;
    for _, node in pairs(self.goldPosList) do
        pauseNode(node);
        node:setVisible(false);
    end

    -- 隐藏所有工人
    for _, node in pairs(self.workerPosList) do
        node:setVisible(false);
    end

    local title = findChildByName(self.node, "TOP/title_bg");
    self.oldTitleVisible = title:isVisible();
    title:setVisible(false);
end

-- 显示底部菜单
function UINewWorkshop:showBottomMenu()
    local BT = self.node:getChildByName("BT");
    local bottom = findChildByName(self.node, "bottom");
    BT:setVisible(true);
    bottom:setVisible(true);

    -- 显示并继续金币产出
    self.waitForClick = false;
    for _, node in pairs(self.goldPosList) do
        resumeNode(node);
        node:setVisible(true);
    end

    -- 显示所有工人
    for _, node in pairs(self.workerPosList) do
        node:setVisible(true);
    end

    local title = findChildByName(self.node, "TOP/title_bg");
    title:setVisible(self.oldTitleVisible);
end

-- 打开二级界面时，隐藏不必要的界面元素
function UINewWorkshop:hideUnneccesElem()
    -- 隐藏底部菜单
    self:hideBottomMenu();

    -- 隐藏药剂师和炼金师冈布奥
    local alchNode = findChildByName(self.node, "bg/alchemist");
    local pharNode = findChildByName(self.node, "bg/pharmacist");
    alchNode:setVisible(false);
    pharNode:setVisible(false);

    -- 隐藏对话框
    for _, ch in pairs(self.wordNodeList) do
        ch:setVisible(false);
    end
end

-- 关闭二级界面时，显示之前隐藏的界面元素
function UINewWorkshop:showUIElem()
    -- 显示底部菜单
    self:showBottomMenu();

    -- 如果有药剂师或炼金师冈布奥，就显示它们
    local alchNode = findChildByName(self.node, "bg/alchemist");
    local pharNode = findChildByName(self.node, "bg/pharmacist");
    if PetM.getMyPet(ALCH_SLIME_ID) then
        alchNode:setVisible(true);
    end
    if PetM.getMyPet(PHAR_SLIME_ID) then
        pharNode:setVisible(true);
    end

    -- 显示对话框
    for _, ch in pairs(self.wordNodeList) do
        ch:setVisible(true);
    end
end

-- 隐藏序章标题
function UINewWorkshop:hideTitle()
    local title = findChildByName(self.node, "TOP/title_bg");
    title:setVisible(false);
end

-- 检查随机发言
function UINewWorkshop:checkRandomWords()
    -- 新手引导时不触发发言
    -- 工人不满10个不发言
    local totalNum = math.min(AlchemyWorkshopM.getTotalWorkerNum());
    if not AlchemyWorkshopM.isAllGuideFinished() or totalNum < 10 then
         return;
    end

    local bg = findChildByName(self.node, "bg");
    -- local scaleX = bg:getScaleX();
    local randomValue = math.random(10);
    if randomValue > 10 then
        return;
    end

    local sceneType = WORKSHOP_TYPE;

    -- 固定三个位置发言
    local posNum = 3;

    -- 随机计算发言的位置， 发言的ID
    local wordsIds = FormulaM.invoke("CALC_RANDOM_WORDS", sceneType, posNum);

    if not wordsIds then
        return;
    end

    -- 显示发言
    for i = 1, #wordsIds do
       local ret = wordsIds[i];
       local wordsId = ret.wordsId;
       local content = RandomWordsM.query(sceneType, wordsId, "content");

       -- 随机发言的位置
       local child = nil;
       local index = ret.pos;
       local wordsNode = findChildByName(self.node, "bg/words_node_"..index);
       wordsNode:removeAllChildren();
       local wordsDelayTime = i*0.4;
       wordsNode:setScale(1.2);
       if index == 1 then
            -- 适配大小
            createWordsFrame(wordsNode, content, WORDS_FRAME_ARROW_BOTTOM_LEFT, 10, wordsDelayTime);
       else
            createWordsFrame(wordsNode, content, WORDS_FRAME_ARROW_BOTTOM_RIGHT, 10, wordsDelayTime);
       end
    end
end

-- 第一和第二次招募冈布奥触发发言
function UINewWorkshop:showWordsDialog(level)
    local bg = findChildByName(self.node, "bg");
    -- local scaleX = bg:getScaleX();
    local content = RandomWordsM.query(WORKSHOP_TYPE, level, "content");

    level = level + 1;

    -- 检查工匠区域2的位置是否为空
    local ret = {4, 5, 6, 7}
    local isAreaUsed = false;
    for _, node in pairs(self.workerPosList) do
        local i = node:getTag();
        if table.indexOf(ret, i) ~= -1 then
             if node.isUsed == true then
                 isAreaUsed = true;
                 break;
             end
        end
    end

    -- 发言区域2为空，发言区域改为1
    if level == 2 and not isAreaUsed then
        level = 1;
    end

    -- 由于words_node最多为4个，因此需要对level做一下修正
    level = math.min(level, 4);

    local wordsNode = findChildByName(self.node, "bg/words_node_"..level);
    wordsNode:setScale(1.2)
    wordsNode:removeAllChildren();
    if level == 2 then
        -- 此处不再发言
        -- createWordsFrame(wordsNode, content, WORDS_FRAME_ARROW_BOTTOM_LEFT, 10);
    end
end

-- 高亮炼金炉泡泡
function UINewWorkshop:highlightWorkshopBubble()
    if self.isHighlightWorkshopBubble then
        return;
    end

    local guideMask = findChildByName(self.node, "guide_mask");
    guideMask:setVisible(true);

    -- 复制一份炼金炉图片
    local furnaceIcon = findChildByName(self.node, "bg/furnace_icon");
    local furnaceCopy = furnaceIcon:clone();
    furnaceCopy:setVisible(true);
    guideMask:addChild(furnaceCopy);

    -- 隐藏原来的炼金炉图片
    furnaceIcon:setVisible(false);

    -- 喷气特效节点
    local furnaceAnim = findChildByName(self.node, "bg/furnace_anim");

    -- 复制喷气节点
    local furnaceAnimCopy = cc.Node:create();
    furnaceAnimCopy:setPosition(furnaceAnim:getPosition());
    guideMask:addChild(furnaceAnimCopy);
    playEffect(furnaceAnimCopy, 1167, 27, 100);

    -- 隐藏喷气特效节点
    furnaceAnim:setVisible(false);

    -- 流水特效节点
    local flowNode = findChildByName(self.node, "bg/flow_node");

    -- 复制流水节点
    local flowNodeCopy = cc.Node:create();
    flowNodeCopy:setPosition(flowNode:getPosition());
    guideMask:addChild(flowNodeCopy);
    playEffect(flowNodeCopy, 1174, 0, 0);

    -- 隐藏流水特效节点
    flowNode:setVisible(false);

    -- 泡泡节点
    local bubble = findChildByName(self.node, "bg/bubble");
    local bubbleCopy = cc.Node:create();
    bubbleCopy:setPosition(bubble:getPosition());
    local bubbleBg = findChildByName(self.node, "bg/bubble/bg");
    local bubbleIcon = findChildByName(self.node, "bg/bubble/icon");
    local bubbleBgCopy = bubbleBg:clone();
    bubbleCopy:addChild(bubbleBgCopy);
    bubbleCopy:addChild(bubbleIcon:clone());
    guideMask:addChild(bubbleCopy);

    bubbleBgCopy:addTouchEventListener(function(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            self:openFurnace();
        end
    end);

    -- 隐藏泡泡节点
    bubble:setVisible(false);

    -- 复制的泡泡节点播放呼吸效果
    playBubbleAnima(bubbleCopy, true, 0.88);

    self.isHighlightWorkshopBubble = true;
end

-- 还原炼金炉泡泡
function UINewWorkshop:restoreWorkshopBubble()
    if not self.isHighlightWorkshopBubble then
        return;
    end

    if AlchemyWorkshopM.getStrengthenLevel(1) == 0 then
        return;
    end

    local guideMask = findChildByName(self.node, "guide_mask");
    guideMask:removeAllChildren();
    guideMask:setVisible(false);

    -- 复制一份炼金炉图片
    local furnaceIcon = findChildByName(self.node, "bg/furnace_icon");
    furnaceIcon:setVisible(true);

    -- 喷气特效节点
    local furnaceAnim = findChildByName(self.node, "bg/furnace_anim");
    furnaceAnim:setVisible(true);

    -- 流水特效节点
    local flowNode = findChildByName(self.node, "bg/flow_node");
    flowNode:setVisible(true);

    -- 泡泡节点
    local bubble = findChildByName(self.node, "bg/bubble");
    bubble:setVisible(false);

    self.isHighlightWorkshopBubble = false;
end

-- 冈布奥说话
function UINewWorkshop:slimeTalk(content)
    local wordNode = findChildByName(self.node, "bg/slime/word");

    local bg = findChildByName(self.node, "bg");
    local scaleX = bg:getScaleX();
    wordNode:setScale(1.2);
    createWordsFrame(wordNode, content, WORDS_FRAME_ARROW_BOTTOM_LEFT, 5, 0.01, TextStyleM.TEXT_COLOR_BLUE);
end

-- 高亮购买装备的泡泡
function UINewWorkshop:highlightBuyEquipBubble()
    if self.isHighlightBuyEquipBubble then
        return;
    end

    local guideMask = findChildByName(self.node, "guide_mask");
    guideMask:setVisible(true);

    local slime = findChildByName(self.node, "bg/slime");
    local slimeCopy = cc.Node:create();
    slimeCopy:setPosition(slime:getPosition());
    guideMask:addChild(slimeCopy);

    -- 复制冈布奥阴影图片
    local slimeShadow = findChildByName(self.node, "bg/slime/shadow");
    local slimeShadowCopy = slimeShadow:clone();
    slimeShadowCopy:setVisible(true);
    slimeCopy:addChild(slimeShadowCopy);

    -- 隐藏原来的冈布奥阴影图片
    slimeShadow:setVisible(false);

    -- 复制冈布奥图片
    local slimeIcon = findChildByName(self.node, "bg/slime/icon");
    local slimeIconCopy = slimeIcon:clone();
    slimeIconCopy:setPosition(0, 0);
    slimeIconCopy:setVisible(true);
    slimeCopy:addChild(slimeIconCopy);

    -- 隐藏原来的冈布奥图片
    slimeIcon:setVisible(false);

    -- 泡泡节点
    local bubble = findChildByName(self.node, "bg/slime/bubble");
    local bubbleCopy = cc.Node:create();
    bubbleCopy:setPosition(bubble:getPosition());
    local bubbleBg = findChildByName(self.node, "bg/slime/bubble/bg");
    local bubbleIcon = findChildByName(self.node, "bg/slime/bubble/icon");
    local bubbleBgCopy = bubbleBg:clone();
    bubbleCopy:addChild(bubbleBgCopy);
    bubbleCopy:addChild(bubbleIcon:clone());
    slimeCopy:addChild(bubbleCopy);

    bubbleBgCopy:addTouchEventListener(function(sender,eventType)
        if eventType == ccui.TouchEventType.ended then
            local uiForm = UIGuideBuyEquip:create();
            UIMgr.getCurrentScene():addForm(uiForm);
            -- 音效
            AudioM.playFx("ui_open1");
        end
    end);

    -- 隐藏泡泡节点
    bubble:setVisible(false);

    -- 复制的泡泡节点播放呼吸效果
    playBubbleAnima(bubbleCopy, true);

    self.isHighlightBuyEquipBubble = true;
end

-- 还原购买装备泡泡
function UINewWorkshop:restoreBuyEquipBubble()
    if not self.isHighlightBuyEquipBubble then
        return;
    end

    local guideMask = findChildByName(self.node, "guide_mask");
    guideMask:removeAllChildren();
    guideMask:setVisible(false);

    local slimeShadow = findChildByName(self.node, "bg/slime/shadow");
    slimeShadow:setVisible(true);

    local slimeIcon = findChildByName(self.node, "bg/slime/icon");
    slimeIcon:setVisible(true);

    self.isHighlightBuyEquipBubble = false;
end

-- 检查是否显示招牌
function UINewWorkshop:checkSign()
    if not SuperiorM.isOverdue() then
        -- 根据月卡的等级来显示招牌
        local monthlyCardSign = findChildByName(self.node, "bg/sign");
        local level = SuperiorM.getSuperiorLevel();
        monthlyCardSign:setVisible(true);
        monthlyCardSign:loadTexture(getSignIcon(level));

        -- 查看是否可以领奖
        local isCanLevelUp = SuperiorM.canUpgrade();
        local isCanTake = SuperiorM.cantakeBonus();
        local hintNode = findChildByName(self.node, "bg/sign/hint");
        checkBlueBubbleStatus(hintNode, isCanTake or isCanLevelUp, 0.75);
    end
end

-- 获取工匠阴影偏移值
function UINewWorkshop:getWorkerShadowOffset(iconPath)
    if iconPath == "images/ui/workshop/worker1.png" then
        return workerShadowOffset[1];
    elseif iconPath == "images/ui/workshop/worker2.png" then
        return workerShadowOffset[2];
    elseif iconPath == "images/ui/workshop/worker3.png" then
        return workerShadowOffset[3];
    else
        return nil;
    end
end

-- 适配
function UINewWorkshop:resize()
    local node = self.node;

    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    local bg = node:getChildByName("bg");
    local scale;
    if h / w >= 1.5 then
        scale = h / 1136;

        -- 调整招牌,在按高缩放时，可能将招牌图标可能在屏幕外。
        local scaleX = w / 768;
        local scaleY = h / 1136;
        local offset = 768 * (scaleX - scaleY) / (2* scale);
        local signImg = findChildByName(bg, "sign");
        signImg:setPosition(signImg:getPositionX() - offset, signImg:getPositionY());
    else
        scale = w / 768;
    end

    bg:setScale(scale);
    bg:setPosition(w / 2, 0);
    self.bg = bg;

    local mask = findChildByName(self.node, "mask");
    mask:setContentSize(w, h);
    mask:setPosition(w / 2, 0);

    local guideMask = findChildByName(self.node, "guide_mask");
    guideMask:setContentSize(768, 1136);
    guideMask:setScale(scale);
    guideMask:setPosition(w / 2, 0);

    -- TOP居中并缩放至合适大小
    AlignM.alignToTopCenter(node, "TOP");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
    AlignM.alignToBottomCenter(node, "bottom");
end
